Fix conflicts for OpenSSH 2.9.
This commit is contained in:
parent
3ed16d1511
commit
ca3176e7c8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=76262
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: auth-chall.c,v 1.7 2001/04/05 10:42:47 markus Exp $");
|
RCSID("$OpenBSD: auth-chall.c,v 1.7 2001/04/05 10:42:47 markus Exp $");
|
||||||
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
@ -69,14 +70,14 @@ verify_response(Authctxt *authctxt, char *response)
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#ifdef SKEY
|
#ifdef SKEY
|
||||||
#include <skey.h>
|
#include <opie.h>
|
||||||
|
|
||||||
char *
|
char *
|
||||||
get_challenge(Authctxt *authctxt, char *devs)
|
get_challenge(Authctxt *authctxt, char *devs)
|
||||||
{
|
{
|
||||||
static char challenge[1024];
|
static char challenge[1024];
|
||||||
struct skey skey;
|
struct opie opie;
|
||||||
if (skeychallenge(&skey, authctxt->user, challenge) == -1)
|
if (opiechallenge(&opie, authctxt->user, challenge) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
strlcat(challenge, "\nS/Key Password: ", sizeof challenge);
|
strlcat(challenge, "\nS/Key Password: ", sizeof challenge);
|
||||||
return challenge;
|
return challenge;
|
||||||
@ -85,8 +86,8 @@ int
|
|||||||
verify_response(Authctxt *authctxt, char *response)
|
verify_response(Authctxt *authctxt, char *response)
|
||||||
{
|
{
|
||||||
return (authctxt->valid &&
|
return (authctxt->valid &&
|
||||||
skey_haskey(authctxt->pw->pw_name) == 0 &&
|
opie_haskey(authctxt->pw->pw_name) == 0 &&
|
||||||
skey_passcheck(authctxt->pw->pw_name, response) != -1);
|
opie_passverify(authctxt->pw->pw_name, response) != -1);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* not available */
|
/* not available */
|
||||||
|
@ -23,13 +23,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
RCSID("$OpenBSD: auth-krb4.c,v 1.23 2001/01/22 08:15:00 markus Exp $");
|
||||||
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include "ssh.h"
|
||||||
|
#include "ssh1.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "log.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
#include "auth.h"
|
||||||
|
|
||||||
RCSID("$OpenBSD: auth-krb4.c,v 1.19 2000/10/03 18:03:02 markus Exp $");
|
#ifdef AFS
|
||||||
RCSID("$FreeBSD$");
|
#include "radix.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef KRB4
|
#ifdef KRB4
|
||||||
char *ticket = NULL;
|
char *ticket = NULL;
|
||||||
@ -47,7 +54,7 @@ auth_krb4_password(struct passwd * pw, const char *password)
|
|||||||
AUTH_DAT adata;
|
AUTH_DAT adata;
|
||||||
KTEXT_ST tkt;
|
KTEXT_ST tkt;
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
unsigned long faddr;
|
u_long faddr;
|
||||||
char localhost[MAXHOSTNAMELEN];
|
char localhost[MAXHOSTNAMELEN];
|
||||||
char phost[INST_SZ];
|
char phost[INST_SZ];
|
||||||
char realm[REALM_SZ];
|
char realm[REALM_SZ];
|
||||||
|
@ -11,30 +11,7 @@
|
|||||||
* incompatible with the protocol description in the RFC file, it must be
|
* incompatible with the protocol description in the RFC file, it must be
|
||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* Copyright (c) 1999 Dug Song. All rights reserved.
|
* Copyright (c) 1999 Dug Song. 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.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -59,39 +36,41 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: auth-passwd.c,v 1.18 2000/10/03 18:03:03 markus Exp $");
|
RCSID("$OpenBSD: auth-passwd.c,v 1.22 2001/03/20 18:57:04 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "ssh.h"
|
|
||||||
#include "servconf.h"
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "servconf.h"
|
||||||
|
#include "auth.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern ServerOptions options;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tries to authenticate the user using password. Returns true if
|
* Tries to authenticate the user using password. Returns true if
|
||||||
* authentication succeeds.
|
* authentication succeeds.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
auth_password(struct passwd * pw, const char *password)
|
auth_password(Authctxt *authctxt, const char *password)
|
||||||
{
|
{
|
||||||
extern ServerOptions options;
|
struct passwd * pw = authctxt->pw;
|
||||||
char *encrypted_password;
|
char *encrypted_password;
|
||||||
|
|
||||||
/* deny if no user. */
|
/* deny if no user. */
|
||||||
if (pw == NULL)
|
if (pw == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
if (pw->pw_uid == 0 && options.permit_root_login == 2)
|
if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
|
||||||
return 0;
|
return 0;
|
||||||
if (*password == '\0' && options.permit_empty_passwd == 0)
|
if (*password == '\0' && options.permit_empty_passwd == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
#ifdef BSD_AUTH
|
||||||
#ifdef SKEY_VIA_PASSWD_IS_DISABLED
|
if (auth_userokay(pw->pw_name, authctxt->style, "auth-ssh",
|
||||||
if (options.skey_authentication == 1) {
|
(char *)password) == 0)
|
||||||
int ret = auth_skey_password(pw, password);
|
return 0;
|
||||||
if (ret == 1 || ret == 0)
|
else
|
||||||
return ret;
|
return 1;
|
||||||
/* Fall back to ordinary passwd authentication. */
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
if (options.kerberos_authentication == 1) {
|
if (options.kerberos_authentication == 1) {
|
||||||
|
@ -13,19 +13,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.17 2000/10/03 18:03:03 markus Exp $");
|
RCSID("$OpenBSD: auth-rh-rsa.c,v 1.23 2001/04/06 21:00:04 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "ssh.h"
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
|
#include "log.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "auth.h"
|
||||||
|
#include "tildexpand.h"
|
||||||
|
#include "canohost.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tries to authenticate the user using the .rhosts file and the host using
|
* Tries to authenticate the user using the .rhosts file and the host using
|
||||||
@ -49,26 +50,27 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key
|
|||||||
if (!auth_rhosts(pw, client_user))
|
if (!auth_rhosts(pw, client_user))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
canonical_hostname = get_canonical_hostname();
|
canonical_hostname = get_canonical_hostname(
|
||||||
|
options.reverse_mapping_check);
|
||||||
|
|
||||||
debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
|
debug("Rhosts RSA authentication: canonical host %.900s", canonical_hostname);
|
||||||
|
|
||||||
/* wrap the RSA key into a 'generic' key */
|
/* wrap the RSA key into a 'generic' key */
|
||||||
client_key = key_new(KEY_RSA);
|
client_key = key_new(KEY_RSA1);
|
||||||
BN_copy(client_key->rsa->e, client_host_key->e);
|
BN_copy(client_key->rsa->e, client_host_key->e);
|
||||||
BN_copy(client_key->rsa->n, client_host_key->n);
|
BN_copy(client_key->rsa->n, client_host_key->n);
|
||||||
found = key_new(KEY_RSA);
|
found = key_new(KEY_RSA1);
|
||||||
|
|
||||||
/* Check if we know the host and its host key. */
|
/* Check if we know the host and its host key. */
|
||||||
host_status = check_host_in_hostfile(SSH_SYSTEM_HOSTFILE, canonical_hostname,
|
host_status = check_host_in_hostfile(_PATH_SSH_SYSTEM_HOSTFILE, canonical_hostname,
|
||||||
client_key, found);
|
client_key, found, NULL);
|
||||||
|
|
||||||
/* Check user host file unless ignored. */
|
/* Check user host file unless ignored. */
|
||||||
if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
|
if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *user_hostfile = tilde_expand_filename(SSH_USER_HOSTFILE, pw->pw_uid);
|
char *user_hostfile = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
|
||||||
/*
|
/*
|
||||||
* Check file permissions of SSH_USER_HOSTFILE, auth_rsa()
|
* Check file permissions of _PATH_SSH_USER_HOSTFILE, auth_rsa()
|
||||||
* did already check pw->pw_dir, but there is a race XXX
|
* did already check pw->pw_dir, but there is a race XXX
|
||||||
*/
|
*/
|
||||||
if (options.strict_modes &&
|
if (options.strict_modes &&
|
||||||
@ -79,9 +81,9 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key
|
|||||||
pw->pw_name, user_hostfile);
|
pw->pw_name, user_hostfile);
|
||||||
} else {
|
} else {
|
||||||
/* XXX race between stat and the following open() */
|
/* XXX race between stat and the following open() */
|
||||||
temporarily_use_uid(pw->pw_uid);
|
temporarily_use_uid(pw);
|
||||||
host_status = check_host_in_hostfile(user_hostfile, canonical_hostname,
|
host_status = check_host_in_hostfile(user_hostfile, canonical_hostname,
|
||||||
client_key, found);
|
client_key, found, NULL);
|
||||||
restore_uid();
|
restore_uid();
|
||||||
}
|
}
|
||||||
xfree(user_hostfile);
|
xfree(user_hostfile);
|
||||||
|
@ -14,22 +14,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: auth-rsa.c,v 1.32 2000/10/14 12:19:45 markus Exp $");
|
RCSID("$OpenBSD: auth-rsa.c,v 1.40 2001/04/06 21:00:07 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "rsa.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "ssh.h"
|
|
||||||
#include "mpaux.h"
|
|
||||||
#include "uidswap.h"
|
|
||||||
#include "match.h"
|
|
||||||
#include "servconf.h"
|
|
||||||
#include "auth-options.h"
|
|
||||||
|
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
|
|
||||||
|
#include "rsa.h"
|
||||||
|
#include "packet.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "ssh1.h"
|
||||||
|
#include "mpaux.h"
|
||||||
|
#include "uidswap.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "auth-options.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "servconf.h"
|
||||||
|
#include "auth.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
@ -38,7 +40,7 @@ extern ServerOptions options;
|
|||||||
* Session identifier that is used to bind key exchange and authentication
|
* Session identifier that is used to bind key exchange and authentication
|
||||||
* responses to a particular session.
|
* responses to a particular session.
|
||||||
*/
|
*/
|
||||||
extern unsigned char session_id[16];
|
extern u_char session_id[16];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The .ssh/authorized_keys file contains public keys, one per line, in the
|
* The .ssh/authorized_keys file contains public keys, one per line, in the
|
||||||
@ -61,9 +63,9 @@ auth_rsa_challenge_dialog(RSA *pk)
|
|||||||
{
|
{
|
||||||
BIGNUM *challenge, *encrypted_challenge;
|
BIGNUM *challenge, *encrypted_challenge;
|
||||||
BN_CTX *ctx;
|
BN_CTX *ctx;
|
||||||
unsigned char buf[32], mdbuf[16], response[16];
|
u_char buf[32], mdbuf[16], response[16];
|
||||||
MD5_CTX md;
|
MD5_CTX md;
|
||||||
unsigned int i;
|
u_int i;
|
||||||
int plen, len;
|
int plen, len;
|
||||||
|
|
||||||
encrypted_challenge = BN_new();
|
encrypted_challenge = BN_new();
|
||||||
@ -121,11 +123,11 @@ auth_rsa_challenge_dialog(RSA *pk)
|
|||||||
int
|
int
|
||||||
auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
||||||
{
|
{
|
||||||
char line[8192], file[1024];
|
char line[8192], file[MAXPATHLEN];
|
||||||
int authenticated;
|
int authenticated;
|
||||||
unsigned int bits;
|
u_int bits;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
unsigned long linenum = 0;
|
u_long linenum = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
RSA *pk;
|
RSA *pk;
|
||||||
|
|
||||||
@ -134,11 +136,11 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Temporarily use the user's uid. */
|
/* Temporarily use the user's uid. */
|
||||||
temporarily_use_uid(pw->pw_uid);
|
temporarily_use_uid(pw);
|
||||||
|
|
||||||
/* The authorized keys. */
|
/* The authorized keys. */
|
||||||
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
|
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
|
||||||
SSH_USER_PERMITTED_KEYS);
|
_PATH_SSH_USER_PERMITTED_KEYS);
|
||||||
|
|
||||||
/* Fail quietly if file does not exist */
|
/* Fail quietly if file does not exist */
|
||||||
if (stat(file, &st) < 0) {
|
if (stat(file, &st) < 0) {
|
||||||
@ -166,10 +168,10 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
|||||||
"bad ownership or modes for '%s'.", pw->pw_name, file);
|
"bad ownership or modes for '%s'.", pw->pw_name, file);
|
||||||
fail = 1;
|
fail = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Check path to SSH_USER_PERMITTED_KEYS */
|
/* Check path to _PATH_SSH_USER_PERMITTED_KEYS */
|
||||||
int i;
|
int i;
|
||||||
static const char *check[] = {
|
static const char *check[] = {
|
||||||
"", SSH_USER_DIR, NULL
|
"", _PATH_SSH_USER_DIR, NULL
|
||||||
};
|
};
|
||||||
for (i = 0; check[i]; i++) {
|
for (i = 0; check[i]; i++) {
|
||||||
snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
|
snprintf(line, sizeof line, "%.500s/%.100s", pw->pw_dir, check[i]);
|
||||||
@ -185,8 +187,8 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
|||||||
}
|
}
|
||||||
if (fail) {
|
if (fail) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
log("%s",buf);
|
log("%s", buf);
|
||||||
packet_send_debug("%s",buf);
|
packet_send_debug("%s", buf);
|
||||||
restore_uid();
|
restore_uid();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -232,19 +234,13 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
|||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
options = NULL;
|
options = NULL;
|
||||||
/*
|
|
||||||
* If our options do not allow this key to be used,
|
|
||||||
* do not send challenge.
|
|
||||||
*/
|
|
||||||
if (!auth_parse_options(pw, options, linenum))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* Parse the key from the line. */
|
/* Parse the key from the line. */
|
||||||
if (!auth_rsa_read_key(&cp, &bits, pk->e, pk->n)) {
|
if (!auth_rsa_read_key(&cp, &bits, pk->e, pk->n)) {
|
||||||
debug("%.100s, line %lu: bad key syntax",
|
debug("%.100s, line %lu: bad key syntax",
|
||||||
SSH_USER_PERMITTED_KEYS, linenum);
|
file, linenum);
|
||||||
packet_send_debug("%.100s, line %lu: bad key syntax",
|
packet_send_debug("%.100s, line %lu: bad key syntax",
|
||||||
SSH_USER_PERMITTED_KEYS, linenum);
|
file, linenum);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* cp now points to the comment part. */
|
/* cp now points to the comment part. */
|
||||||
@ -260,6 +256,12 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
|
|||||||
file, linenum, BN_num_bits(pk->n), bits);
|
file, linenum, BN_num_bits(pk->n), bits);
|
||||||
|
|
||||||
/* We have found the desired key. */
|
/* We have found the desired key. */
|
||||||
|
/*
|
||||||
|
* If our options do not allow this key to be used,
|
||||||
|
* do not send challenge.
|
||||||
|
*/
|
||||||
|
if (!auth_parse_options(pw, options, file, linenum))
|
||||||
|
continue;
|
||||||
|
|
||||||
/* Perform the challenge-response dialog for this key. */
|
/* Perform the challenge-response dialog for this key. */
|
||||||
if (!auth_rsa_challenge_dialog(pk)) {
|
if (!auth_rsa_challenge_dialog(pk)) {
|
||||||
|
@ -1,15 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
* All rights reserved
|
|
||||||
*
|
|
||||||
* As far as I am concerned, the code I have written for this software
|
|
||||||
* can be used freely for any purpose. Any derived versions of this
|
|
||||||
* software must be clearly marked as such, and if the derived work is
|
|
||||||
* incompatible with the protocol description in the RFC file, it must be
|
|
||||||
* called by a name other than "ssh" or "Secure Shell".
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -33,35 +23,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: auth.c,v 1.11 2000/10/11 20:27:23 markus Exp $");
|
RCSID("$OpenBSD: auth.c,v 1.21 2001/03/19 17:07:23 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "rsa.h"
|
|
||||||
#include "ssh.h"
|
|
||||||
#include "pty.h"
|
|
||||||
#include "packet.h"
|
|
||||||
#include "buffer.h"
|
|
||||||
#include "mpaux.h"
|
|
||||||
#include "servconf.h"
|
|
||||||
#include "compat.h"
|
|
||||||
#include "channels.h"
|
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
|
#include "groupaccess.h"
|
||||||
#include "bufaux.h"
|
#include "log.h"
|
||||||
#include "ssh2.h"
|
#include "servconf.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "session.h"
|
#include "auth-options.h"
|
||||||
|
#include "canohost.h"
|
||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the user is allowed to log in via ssh. If user is listed in
|
* Check if the user is allowed to log in via ssh. If user is listed
|
||||||
* DenyUsers or user's primary group is listed in DenyGroups, false will
|
* in DenyUsers or one of user's groups is listed in DenyGroups, false
|
||||||
* be returned. If AllowUsers isn't empty and user isn't listed there, or
|
* will be returned. If AllowUsers isn't empty and user isn't listed
|
||||||
* if AllowGroups isn't empty and user isn't listed there, false will be
|
* there, or if AllowGroups isn't empty and one of user's groups isn't
|
||||||
* returned.
|
* listed there, false will be returned.
|
||||||
* If the user's shell is not executable, false will be returned.
|
* If the user's shell is not executable, false will be returned.
|
||||||
* Otherwise true is returned.
|
* Otherwise true is returned.
|
||||||
*/
|
*/
|
||||||
@ -69,12 +51,11 @@ int
|
|||||||
allowed_user(struct passwd * pw)
|
allowed_user(struct passwd * pw)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct group *grp;
|
|
||||||
char *shell;
|
char *shell;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Shouldn't be called if pw is NULL, but better safe than sorry... */
|
/* Shouldn't be called if pw is NULL, but better safe than sorry... */
|
||||||
if (!pw)
|
if (!pw || !pw->pw_name)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -91,16 +72,12 @@ allowed_user(struct passwd * pw)
|
|||||||
|
|
||||||
/* Return false if user is listed in DenyUsers */
|
/* Return false if user is listed in DenyUsers */
|
||||||
if (options.num_deny_users > 0) {
|
if (options.num_deny_users > 0) {
|
||||||
if (!pw->pw_name)
|
|
||||||
return 0;
|
|
||||||
for (i = 0; i < options.num_deny_users; i++)
|
for (i = 0; i < options.num_deny_users; i++)
|
||||||
if (match_pattern(pw->pw_name, options.deny_users[i]))
|
if (match_pattern(pw->pw_name, options.deny_users[i]))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Return false if AllowUsers isn't empty and user isn't listed there */
|
/* Return false if AllowUsers isn't empty and user isn't listed there */
|
||||||
if (options.num_allow_users > 0) {
|
if (options.num_allow_users > 0) {
|
||||||
if (!pw->pw_name)
|
|
||||||
return 0;
|
|
||||||
for (i = 0; i < options.num_allow_users; i++)
|
for (i = 0; i < options.num_allow_users; i++)
|
||||||
if (match_pattern(pw->pw_name, options.allow_users[i]))
|
if (match_pattern(pw->pw_name, options.allow_users[i]))
|
||||||
break;
|
break;
|
||||||
@ -108,36 +85,91 @@ allowed_user(struct passwd * pw)
|
|||||||
if (i >= options.num_allow_users)
|
if (i >= options.num_allow_users)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Get the primary group name if we need it. Return false if it fails */
|
|
||||||
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
|
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
|
||||||
grp = getgrgid(pw->pw_gid);
|
/* Get the user's group access list (primary and supplementary) */
|
||||||
if (!grp)
|
if (ga_init(pw->pw_name, pw->pw_gid) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Return false if user's group is listed in DenyGroups */
|
/* Return false if one of user's groups is listed in DenyGroups */
|
||||||
if (options.num_deny_groups > 0) {
|
if (options.num_deny_groups > 0)
|
||||||
if (!grp->gr_name)
|
if (ga_match(options.deny_groups,
|
||||||
|
options.num_deny_groups)) {
|
||||||
|
ga_free();
|
||||||
return 0;
|
return 0;
|
||||||
for (i = 0; i < options.num_deny_groups; i++)
|
}
|
||||||
if (match_pattern(grp->gr_name, options.deny_groups[i]))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
* Return false if AllowGroups isn't empty and user's group
|
* Return false if AllowGroups isn't empty and one of user's groups
|
||||||
* isn't listed there
|
* isn't listed there
|
||||||
*/
|
*/
|
||||||
if (options.num_allow_groups > 0) {
|
if (options.num_allow_groups > 0)
|
||||||
if (!grp->gr_name)
|
if (!ga_match(options.allow_groups,
|
||||||
|
options.num_allow_groups)) {
|
||||||
|
ga_free();
|
||||||
return 0;
|
return 0;
|
||||||
for (i = 0; i < options.num_allow_groups; i++)
|
}
|
||||||
if (match_pattern(grp->gr_name, options.allow_groups[i]))
|
ga_free();
|
||||||
break;
|
|
||||||
/* i < options.num_allow_groups iff we break for
|
|
||||||
loop */
|
|
||||||
if (i >= options.num_allow_groups)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* We found no reason not to let this user try to log on... */
|
/* We found no reason not to let this user try to log on... */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Authctxt *
|
||||||
|
authctxt_new(void)
|
||||||
|
{
|
||||||
|
Authctxt *authctxt = xmalloc(sizeof(*authctxt));
|
||||||
|
memset(authctxt, 0, sizeof(*authctxt));
|
||||||
|
return authctxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
auth_log(Authctxt *authctxt, int authenticated, char *method, char *info)
|
||||||
|
{
|
||||||
|
void (*authlog) (const char *fmt,...) = verbose;
|
||||||
|
char *authmsg;
|
||||||
|
|
||||||
|
/* Raise logging level */
|
||||||
|
if (authenticated == 1 ||
|
||||||
|
!authctxt->valid ||
|
||||||
|
authctxt->failures >= AUTH_FAIL_LOG ||
|
||||||
|
strcmp(method, "password") == 0)
|
||||||
|
authlog = log;
|
||||||
|
|
||||||
|
if (authctxt->postponed)
|
||||||
|
authmsg = "Postponed";
|
||||||
|
else
|
||||||
|
authmsg = authenticated ? "Accepted" : "Failed";
|
||||||
|
|
||||||
|
authlog("%s %s for %s%.100s from %.200s port %d%s",
|
||||||
|
authmsg,
|
||||||
|
method,
|
||||||
|
authctxt->valid ? "" : "illegal user ",
|
||||||
|
authctxt->valid && authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user,
|
||||||
|
get_remote_ipaddr(),
|
||||||
|
get_remote_port(),
|
||||||
|
info);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether root logins are disallowed.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
auth_root_allowed(char *method)
|
||||||
|
{
|
||||||
|
switch (options.permit_root_login) {
|
||||||
|
case PERMIT_YES:
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case PERMIT_NO_PASSWD:
|
||||||
|
if (strcmp(method, "password") != 0)
|
||||||
|
return 1;
|
||||||
|
break;
|
||||||
|
case PERMIT_FORCED_ONLY:
|
||||||
|
if (forced_command) {
|
||||||
|
log("Root login accepted for forced command.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* $OpenBSD: auth.h,v 1.15 2001/04/12 19:15:24 markus Exp $
|
* $OpenBSD: auth.h,v 1.15 2001/04/12 19:15:24 markus Exp $
|
||||||
|
* $FreeBSD$
|
||||||
*/
|
*/
|
||||||
#ifndef AUTH_H
|
#ifndef AUTH_H
|
||||||
#define AUTH_H
|
#define AUTH_H
|
||||||
@ -96,6 +97,15 @@ int auth_rsa_read_key(char **cpp, u_int *bitsp, BIGNUM * e, BIGNUM * n);
|
|||||||
*/
|
*/
|
||||||
int auth_rsa_challenge_dialog(RSA *pk);
|
int auth_rsa_challenge_dialog(RSA *pk);
|
||||||
|
|
||||||
|
#ifdef KRB5
|
||||||
|
#include <krb5.h>
|
||||||
|
int auth_krb5(); /* XXX Doplnit prototypy */
|
||||||
|
int auth_krb5_tgt();
|
||||||
|
int krb5_init();
|
||||||
|
void krb5_cleanup_proc(void *ignore);
|
||||||
|
int auth_krb5_password(struct passwd *pw, const char *password);
|
||||||
|
#endif /* KRB5 */
|
||||||
|
|
||||||
#ifdef KRB4
|
#ifdef KRB4
|
||||||
#include <krb.h>
|
#include <krb.h>
|
||||||
/*
|
/*
|
||||||
|
@ -10,19 +10,23 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: auth1.c,v 1.6 2000/10/11 20:27:23 markus Exp $");
|
RCSID("$OpenBSD: auth1.c,v 1.22 2001/03/23 12:02:49 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "ssh.h"
|
#include "ssh1.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "mpaux.h"
|
#include "mpaux.h"
|
||||||
|
#include "log.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
|
#include "auth-pam.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
|
#include "canohost.h"
|
||||||
|
#include "misc.h"
|
||||||
#include <login_cap.h>
|
#include <login_cap.h>
|
||||||
#include <security/pam_appl.h>
|
#include <security/pam_appl.h>
|
||||||
|
|
||||||
@ -34,7 +38,6 @@ Also is used as an indication of succesful krb5 authentization. */
|
|||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
extern char *forced_command;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* convert ssh auth msg type into description
|
* convert ssh auth msg type into description
|
||||||
@ -52,13 +55,12 @@ get_authname(int type)
|
|||||||
return "rhosts-rsa";
|
return "rhosts-rsa";
|
||||||
case SSH_CMSG_AUTH_RHOSTS:
|
case SSH_CMSG_AUTH_RHOSTS:
|
||||||
return "rhosts";
|
return "rhosts";
|
||||||
|
case SSH_CMSG_AUTH_TIS:
|
||||||
|
case SSH_CMSG_AUTH_TIS_RESPONSE:
|
||||||
|
return "challenge-response";
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
case SSH_CMSG_AUTH_KERBEROS:
|
case SSH_CMSG_AUTH_KERBEROS:
|
||||||
return "kerberos";
|
return "kerberos";
|
||||||
#endif
|
|
||||||
#ifdef SKEY
|
|
||||||
case SSH_CMSG_AUTH_TIS_RESPONSE:
|
|
||||||
return "s/key";
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
|
snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
|
||||||
@ -66,26 +68,23 @@ get_authname(int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* read packets and try to authenticate local user 'luser'.
|
* read packets, try to authenticate the user and
|
||||||
* return if authentication is successfull. not that pw == NULL
|
* return only if authentication is successful
|
||||||
* if the user does not exists or is not allowed to login.
|
|
||||||
* each auth method has to 'fake' authentication for nonexisting
|
|
||||||
* users.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
do_authloop(struct passwd * pw, char *luser)
|
do_authloop(Authctxt *authctxt)
|
||||||
{
|
{
|
||||||
int authenticated = 0;
|
int authenticated = 0;
|
||||||
int attempt = 0;
|
u_int bits;
|
||||||
unsigned int bits;
|
|
||||||
RSA *client_host_key;
|
RSA *client_host_key;
|
||||||
BIGNUM *n;
|
BIGNUM *n;
|
||||||
char *client_user, *password;
|
char *client_user, *password;
|
||||||
char user[1024];
|
char info[1024];
|
||||||
unsigned int dlen;
|
u_int dlen;
|
||||||
int plen, nlen, elen;
|
int plen, nlen, elen;
|
||||||
unsigned int ulen;
|
u_int ulen;
|
||||||
int type = 0;
|
int type = 0;
|
||||||
|
struct passwd *pw = authctxt->pw;
|
||||||
void (*authlog) (const char *fmt,...) = verbose;
|
void (*authlog) (const char *fmt,...) = verbose;
|
||||||
#ifdef HAVE_LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
login_cap_t *lc;
|
login_cap_t *lc;
|
||||||
@ -96,7 +95,7 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
|
#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
|
||||||
const char *from_host, *from_ip;
|
const char *from_host, *from_ip;
|
||||||
|
|
||||||
from_host = get_canonical_hostname();
|
from_host = get_canonical_hostname(options.reverse_mapping_check);
|
||||||
from_ip = get_remote_ipaddr();
|
from_ip = get_remote_ipaddr();
|
||||||
#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
|
#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
|
||||||
#if 0
|
#if 0
|
||||||
@ -113,6 +112,24 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
#endif /* KRB5 */
|
#endif /* KRB5 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
debug("Attempting authentication for %s%.100s.",
|
||||||
|
authctxt->valid ? "" : "illegal user ", authctxt->user);
|
||||||
|
|
||||||
|
/* If the user has no password, accept authentication immediately. */
|
||||||
|
if (options.password_authentication &&
|
||||||
|
#if defined(KRB4) || defined(KRB5)
|
||||||
|
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
|
||||||
|
#endif
|
||||||
|
#ifdef USE_PAM
|
||||||
|
auth_pam_password(authctxt, "")
|
||||||
|
#else
|
||||||
|
auth_password(authctxt, "")
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
auth_log(authctxt, 1, "without authentication", "");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Indicate that authentication is needed. */
|
/* Indicate that authentication is needed. */
|
||||||
packet_start(SSH_SMSG_FAILURE);
|
packet_start(SSH_SMSG_FAILURE);
|
||||||
packet_send();
|
packet_send();
|
||||||
@ -120,11 +137,11 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
|
|
||||||
client_user = NULL;
|
client_user = NULL;
|
||||||
|
|
||||||
for (attempt = 1;; attempt++) {
|
for (;;) {
|
||||||
/* default to fail */
|
/* default to fail */
|
||||||
authenticated = 0;
|
authenticated = 0;
|
||||||
|
|
||||||
strlcpy(user, "", sizeof user);
|
info[0] = '\0';
|
||||||
|
|
||||||
/* Get a packet from the client. */
|
/* Get a packet from the client. */
|
||||||
type = packet_read(&plen);
|
type = packet_read(&plen);
|
||||||
@ -143,7 +160,7 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
char *tgt = packet_get_string(&dlen);
|
char *tgt = packet_get_string(&dlen);
|
||||||
packet_integrity_check(plen, 4 + dlen, type);
|
packet_integrity_check(plen, 4 + dlen, type);
|
||||||
if (!auth_krb4_tgt(pw, tgt))
|
if (!auth_krb4_tgt(pw, tgt))
|
||||||
verbose("Kerberos v4 tgt REFUSED for %s", luser);
|
verbose("Kerberos v4 tgt REFUSED for %.100ss", authctxt->user);
|
||||||
xfree(tgt);
|
xfree(tgt);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -157,7 +174,7 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
char *token_string = packet_get_string(&dlen);
|
char *token_string = packet_get_string(&dlen);
|
||||||
packet_integrity_check(plen, 4 + dlen, type);
|
packet_integrity_check(plen, 4 + dlen, type);
|
||||||
if (!auth_afs_token(pw, token_string))
|
if (!auth_afs_token(pw, token_string))
|
||||||
verbose("AFS token REFUSED for %.100s", luser);
|
verbose("AFS token REFUSED for %.100s", authctxt->user);
|
||||||
xfree(token_string);
|
xfree(token_string);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@ -166,35 +183,36 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
case SSH_CMSG_AUTH_KERBEROS:
|
case SSH_CMSG_AUTH_KERBEROS:
|
||||||
if (!options.kerberos_authentication) {
|
if (!options.kerberos_authentication) {
|
||||||
verbose("Kerberos authentication disabled.");
|
verbose("Kerberos authentication disabled.");
|
||||||
} else {
|
break;
|
||||||
unsigned int length;
|
} else {
|
||||||
char *kdata = packet_get_string(&length);
|
/* Try Kerberos authentication. */
|
||||||
packet_integrity_check(plen, 4 + length, type);
|
KTEXT_ST auth;
|
||||||
|
char *tkt_user = NULL;
|
||||||
|
char *kdata = packet_get_string((u_int *) &auth.length);
|
||||||
|
packet_integrity_check(plen, 4 + auth.length, type);
|
||||||
|
|
||||||
/* 4 == KRB_PROT_VERSION */
|
if (!authctxt->valid) {
|
||||||
if (kdata[0] == 4) {
|
/* Do nothing. */
|
||||||
#ifndef KRB4
|
} else if (kdata[0] == 4) { /* 4 == KRB_PROT_VERSION */
|
||||||
verbose("Kerberos v4 authentication disabled.");
|
#ifdef KRB4
|
||||||
#else
|
|
||||||
char *tkt_user = NULL;
|
|
||||||
KTEXT_ST auth;
|
|
||||||
auth.length = length;
|
|
||||||
if (auth.length < MAX_KTXT_LEN)
|
if (auth.length < MAX_KTXT_LEN)
|
||||||
memcpy(auth.dat, kdata, auth.length);
|
memcpy(auth.dat, kdata, auth.length);
|
||||||
|
|
||||||
authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
|
authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
|
||||||
|
|
||||||
if (authenticated) {
|
if (authenticated) {
|
||||||
snprintf(user, sizeof user, " tktuser %s", tkt_user);
|
snprintf(info, sizeof info,
|
||||||
|
" tktuser %.100s", tkt_user);
|
||||||
xfree(tkt_user);
|
xfree(tkt_user);
|
||||||
}
|
}
|
||||||
#endif /* KRB4 */
|
#else
|
||||||
|
verbose("Kerberos v4 authentication disabled.");
|
||||||
|
#endif /* KRB4 */
|
||||||
} else {
|
} else {
|
||||||
#ifndef KRB5
|
#ifndef KRB5
|
||||||
verbose("Kerberos v5 authentication disabled.");
|
verbose("Kerberos v5 authentication disabled.");
|
||||||
#else
|
#else
|
||||||
krb5_data k5data;
|
krb5_data k5data;
|
||||||
k5data.length = length;
|
k5data.length = auth.length;
|
||||||
k5data.data = kdata;
|
k5data.data = kdata;
|
||||||
#if 0
|
#if 0
|
||||||
if (krb5_init_context(&ssh_context)) {
|
if (krb5_init_context(&ssh_context)) {
|
||||||
@ -235,7 +253,7 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
|
/* Try to authenticate using /etc/hosts.equiv and .rhosts. */
|
||||||
authenticated = auth_rhosts(pw, client_user);
|
authenticated = auth_rhosts(pw, client_user);
|
||||||
|
|
||||||
snprintf(user, sizeof user, " ruser %s", client_user);
|
snprintf(info, sizeof info, " ruser %.100s", client_user);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSH_CMSG_AUTH_RHOSTS_RSA:
|
case SSH_CMSG_AUTH_RHOSTS_RSA:
|
||||||
@ -270,7 +288,7 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
|
authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
|
||||||
RSA_free(client_host_key);
|
RSA_free(client_host_key);
|
||||||
|
|
||||||
snprintf(user, sizeof user, " ruser %s", client_user);
|
snprintf(info, sizeof info, " ruser %.100s", client_user);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SSH_CMSG_AUTH_RSA:
|
case SSH_CMSG_AUTH_RSA:
|
||||||
@ -301,10 +319,10 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
/* Do PAM auth with password */
|
/* Do PAM auth with password */
|
||||||
authenticated = auth_pam_password(pw, password);
|
authenticated = auth_pam_password(authctxt, password);
|
||||||
#else /* !USE_PAM */
|
#else /* !USE_PAM */
|
||||||
/* Try authentication with the password. */
|
/* Try authentication with the password. */
|
||||||
authenticated = auth_password(pw, password);
|
authenticated = auth_password(authctxt, password);
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
|
|
||||||
memset(password, 0, strlen(password));
|
memset(password, 0, strlen(password));
|
||||||
@ -347,18 +365,12 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
#elif defined(SKEY)
|
#elif defined(SKEY)
|
||||||
case SSH_CMSG_AUTH_TIS:
|
case SSH_CMSG_AUTH_TIS:
|
||||||
debug("rcvd SSH_CMSG_AUTH_TIS");
|
debug("rcvd SSH_CMSG_AUTH_TIS");
|
||||||
if (options.skey_authentication == 1) {
|
if (options.challenge_reponse_authentication == 1) {
|
||||||
char *skeyinfo = pw ? opie_keyinfo(pw->pw_name) :
|
char *challenge = get_challenge(authctxt, authctxt->style);
|
||||||
NULL;
|
if (challenge != NULL) {
|
||||||
if (skeyinfo == NULL) {
|
debug("sending challenge '%s'", challenge);
|
||||||
debug("generating fake skeyinfo for %.100s.", luser);
|
|
||||||
skeyinfo = skey_fake_keyinfo(luser);
|
|
||||||
}
|
|
||||||
if (skeyinfo != NULL) {
|
|
||||||
/* we send our s/key- in tis-challenge messages */
|
|
||||||
debug("sending challenge '%s'", skeyinfo);
|
|
||||||
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
|
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
|
||||||
packet_put_cstring(skeyinfo);
|
packet_put_cstring(challenge);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
continue;
|
continue;
|
||||||
@ -367,13 +379,12 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
break;
|
break;
|
||||||
case SSH_CMSG_AUTH_TIS_RESPONSE:
|
case SSH_CMSG_AUTH_TIS_RESPONSE:
|
||||||
debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
|
debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
|
||||||
if (options.skey_authentication == 1) {
|
if (options.challenge_reponse_authentication == 1) {
|
||||||
char *response = packet_get_string(&dlen);
|
char *response = packet_get_string(&dlen);
|
||||||
debug("skey response == '%s'", response);
|
debug("got response '%s'", response);
|
||||||
packet_integrity_check(plen, 4 + dlen, type);
|
packet_integrity_check(plen, 4 + dlen, type);
|
||||||
authenticated = (pw != NULL &&
|
authenticated = verify_response(authctxt, response);
|
||||||
opie_haskey(pw->pw_name) == 0 &&
|
memset(response, 'r', dlen);
|
||||||
opie_passverify(pw->pw_name, response) != -1);
|
|
||||||
xfree(response);
|
xfree(response);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -417,23 +428,6 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
log("Unknown message during authentication: type %d", type);
|
log("Unknown message during authentication: type %d", type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (authenticated && pw == NULL)
|
|
||||||
fatal("internal error: authenticated for pw == NULL");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the user is logging in as root and root logins
|
|
||||||
* are disallowed.
|
|
||||||
* Note that root login is allowed for forced commands.
|
|
||||||
*/
|
|
||||||
if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) {
|
|
||||||
if (forced_command) {
|
|
||||||
log("Root login accepted for forced command.");
|
|
||||||
} else {
|
|
||||||
authenticated = 0;
|
|
||||||
log("ROOT LOGIN REFUSED FROM %.200s",
|
|
||||||
get_canonical_hostname());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
if (pw != NULL) {
|
if (pw != NULL) {
|
||||||
@ -461,28 +455,28 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
packet_disconnect("Sorry, you are not allowed to connect.");
|
packet_disconnect("Sorry, you are not allowed to connect.");
|
||||||
}
|
}
|
||||||
#endif /* LOGIN_ACCESS */
|
#endif /* LOGIN_ACCESS */
|
||||||
|
#ifdef BSD_AUTH
|
||||||
|
if (authctxt->as) {
|
||||||
|
auth_close(authctxt->as);
|
||||||
|
authctxt->as = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!authctxt->valid && authenticated)
|
||||||
|
fatal("INTERNAL ERROR: authenticated invalid user %s",
|
||||||
|
authctxt->user);
|
||||||
|
|
||||||
|
/* Special handling for root */
|
||||||
|
if (authenticated && authctxt->pw->pw_uid == 0 &&
|
||||||
|
!auth_root_allowed(get_authname(type)))
|
||||||
|
authenticated = 0;
|
||||||
|
|
||||||
if (pw != NULL && pw->pw_uid == 0)
|
if (pw != NULL && pw->pw_uid == 0)
|
||||||
log("ROOT LOGIN as '%.100s' from %.100s",
|
log("ROOT LOGIN as '%.100s' from %.100s",
|
||||||
pw->pw_name, get_canonical_hostname());
|
pw->pw_name,
|
||||||
|
get_canonical_hostname(options.reverse_mapping_check));
|
||||||
|
|
||||||
/* Raise logging level */
|
/* Log before sending the reply */
|
||||||
if (authenticated ||
|
auth_log(authctxt, authenticated, get_authname(type), info);
|
||||||
attempt == AUTH_FAIL_LOG ||
|
|
||||||
type == SSH_CMSG_AUTH_PASSWORD)
|
|
||||||
authlog = log;
|
|
||||||
|
|
||||||
authlog("%s %s for %s%.100s from %.200s port %d%s",
|
|
||||||
authenticated ? "Accepted" : "Failed",
|
|
||||||
get_authname(type),
|
|
||||||
pw ? "" : "illegal user ",
|
|
||||||
pw && pw->pw_uid == 0 ? "ROOT" : luser,
|
|
||||||
get_remote_ipaddr(),
|
|
||||||
get_remote_port(),
|
|
||||||
user);
|
|
||||||
|
|
||||||
if (authenticated)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
if (authenticated && !do_pam_account(pw->pw_name, client_user))
|
if (authenticated && !do_pam_account(pw->pw_name, client_user))
|
||||||
@ -494,10 +488,12 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
client_user = NULL;
|
client_user = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attempt > AUTH_FAIL_MAX)
|
if (authenticated)
|
||||||
packet_disconnect(AUTH_FAIL_MSG, luser);
|
return;
|
||||||
|
|
||||||
|
if (authctxt->failures++ > AUTH_FAIL_MAX)
|
||||||
|
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
|
||||||
|
|
||||||
/* Send a message indicating that the authentication attempt failed. */
|
|
||||||
packet_start(SSH_SMSG_FAILURE);
|
packet_start(SSH_SMSG_FAILURE);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
@ -511,10 +507,11 @@ do_authloop(struct passwd * pw, char *luser)
|
|||||||
void
|
void
|
||||||
do_authentication()
|
do_authentication()
|
||||||
{
|
{
|
||||||
struct passwd *pw, pwcopy;
|
Authctxt *authctxt;
|
||||||
|
struct passwd *pw;
|
||||||
int plen;
|
int plen;
|
||||||
unsigned int ulen;
|
u_int ulen;
|
||||||
char *user;
|
char *user, *style = NULL;
|
||||||
|
|
||||||
/* Get the name of the user that we wish to log in as. */
|
/* Get the name of the user that we wish to log in as. */
|
||||||
packet_read_expect(&plen, SSH_CMSG_USER);
|
packet_read_expect(&plen, SSH_CMSG_USER);
|
||||||
@ -523,39 +520,30 @@ do_authentication()
|
|||||||
user = packet_get_string(&ulen);
|
user = packet_get_string(&ulen);
|
||||||
packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
|
packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
|
||||||
|
|
||||||
setproctitle("%s", user);
|
if ((style = strchr(user, ':')) != NULL)
|
||||||
|
*style++ = 0;
|
||||||
|
|
||||||
#ifdef AFS
|
authctxt = authctxt_new();
|
||||||
/* If machine has AFS, set process authentication group. */
|
authctxt->user = user;
|
||||||
if (k_hasafs()) {
|
authctxt->style = style;
|
||||||
k_setpag();
|
|
||||||
k_unlog();
|
|
||||||
}
|
|
||||||
#endif /* AFS */
|
|
||||||
|
|
||||||
/* Verify that the user is a valid user. */
|
/* Verify that the user is a valid user. */
|
||||||
pw = getpwnam(user);
|
pw = getpwnam(user);
|
||||||
if (pw && allowed_user(pw)) {
|
if (pw && allowed_user(pw)) {
|
||||||
/* Take a copy of the returned structure. */
|
authctxt->valid = 1;
|
||||||
memset(&pwcopy, 0, sizeof(pwcopy));
|
pw = pwcopy(pw);
|
||||||
pwcopy.pw_name = xstrdup(pw->pw_name);
|
|
||||||
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
|
||||||
pwcopy.pw_uid = pw->pw_uid;
|
|
||||||
pwcopy.pw_gid = pw->pw_gid;
|
|
||||||
pwcopy.pw_class = xstrdup(pw->pw_class);
|
|
||||||
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
|
||||||
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
|
||||||
pwcopy.pw_expire = pw->pw_expire;
|
|
||||||
pwcopy.pw_change = pw->pw_change;
|
|
||||||
pw = &pwcopy;
|
|
||||||
} else {
|
} else {
|
||||||
|
debug("do_authentication: illegal user %s", user);
|
||||||
pw = NULL;
|
pw = NULL;
|
||||||
}
|
}
|
||||||
|
authctxt->pw = pw;
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
if (pw != NULL)
|
if (pw != NULL)
|
||||||
start_pam(pw);
|
start_pam(pw);
|
||||||
#endif
|
#endif
|
||||||
|
setproctitle("%s", pw ? user : "unknown");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are not running as root, the user must have the same uid as
|
* If we are not running as root, the user must have the same uid as
|
||||||
* the server.
|
* the server.
|
||||||
@ -563,33 +551,11 @@ do_authentication()
|
|||||||
if (getuid() != 0 && pw && pw->pw_uid != getuid())
|
if (getuid() != 0 && pw && pw->pw_uid != getuid())
|
||||||
packet_disconnect("Cannot change user when server not running as root.");
|
packet_disconnect("Cannot change user when server not running as root.");
|
||||||
|
|
||||||
debug("Attempting authentication for %s%.100s.", pw ? "" : "illegal user ", user);
|
/*
|
||||||
|
* Loop until the user has been authenticated or the connection is
|
||||||
/* If the user has no password, accept authentication immediately. */
|
* closed, do_authloop() returns only if authentication is successful
|
||||||
if (options.password_authentication &&
|
*/
|
||||||
#ifdef KRB5
|
do_authloop(authctxt);
|
||||||
!options.kerberos_authentication &&
|
|
||||||
#endif /* KRB5 */
|
|
||||||
#ifdef KRB4
|
|
||||||
(!options.kerberos_authentication || options.krb4_or_local_passwd) &&
|
|
||||||
#endif /* KRB4 */
|
|
||||||
#ifdef USE_PAM
|
|
||||||
auth_pam_password(pw, "")
|
|
||||||
#else /* !USE_PAM */
|
|
||||||
auth_password(pw, "")
|
|
||||||
#endif /* USE_PAM */
|
|
||||||
) {
|
|
||||||
/* Authentication with empty password succeeded. */
|
|
||||||
log("Login for user %s from %.100s, accepted without authentication.",
|
|
||||||
user, get_remote_ipaddr());
|
|
||||||
} else {
|
|
||||||
/* Loop until the user has been authenticated or the
|
|
||||||
connection is closed, do_authloop() returns only if
|
|
||||||
authentication is successfull */
|
|
||||||
do_authloop(pw, user);
|
|
||||||
}
|
|
||||||
if (pw == NULL)
|
|
||||||
fatal("internal error, authentication successfull for user '%.100s'", user);
|
|
||||||
|
|
||||||
/* The user has been authenticated and accepted. */
|
/* The user has been authenticated and accepted. */
|
||||||
packet_start(SSH_SMSG_SUCCESS);
|
packet_start(SSH_SMSG_SUCCESS);
|
||||||
@ -597,5 +563,5 @@ do_authentication()
|
|||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
|
|
||||||
/* Perform session preparation. */
|
/* Perform session preparation. */
|
||||||
do_authenticated(pw);
|
do_authenticated(authctxt);
|
||||||
}
|
}
|
||||||
|
@ -23,34 +23,35 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: auth2.c,v 1.20 2000/10/14 12:16:56 markus Exp $");
|
RCSID("$OpenBSD: auth2.c,v 1.56 2001/04/19 00:05:11 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#include "ssh2.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "ssh.h"
|
#include "sshpty.h"
|
||||||
#include "pty.h"
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "log.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
#include "ssh2.h"
|
|
||||||
#include "auth.h"
|
#include "auth.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "auth.h"
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
#include "cipher.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
|
#include "pathnames.h"
|
||||||
#include "dsa.h"
|
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "auth-options.h"
|
#include "auth-options.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "hostfile.h"
|
||||||
|
#include "canohost.h"
|
||||||
|
#include "tildexpand.h"
|
||||||
|
|
||||||
#ifdef HAVE_LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
#include <login_cap.h>
|
#include <login_cap.h>
|
||||||
@ -58,7 +59,7 @@ RCSID("$FreeBSD$");
|
|||||||
|
|
||||||
/* import */
|
/* import */
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
extern unsigned char *session_id2;
|
extern u_char *session_id2;
|
||||||
extern int session_id2_len;
|
extern int session_id2_len;
|
||||||
|
|
||||||
static Authctxt *x_authctxt = NULL;
|
static Authctxt *x_authctxt = NULL;
|
||||||
@ -77,17 +78,21 @@ void input_service_request(int type, int plen, void *ctxt);
|
|||||||
void input_userauth_request(int type, int plen, void *ctxt);
|
void input_userauth_request(int type, int plen, void *ctxt);
|
||||||
void protocol_error(int type, int plen, void *ctxt);
|
void protocol_error(int type, int plen, void *ctxt);
|
||||||
|
|
||||||
|
|
||||||
/* helper */
|
/* helper */
|
||||||
Authmethod *authmethod_lookup(const char *name);
|
Authmethod *authmethod_lookup(const char *name);
|
||||||
struct passwd *pwcopy(struct passwd *pw);
|
|
||||||
int user_dsa_key_allowed(struct passwd *pw, Key *key);
|
|
||||||
char *authmethods_get(void);
|
char *authmethods_get(void);
|
||||||
|
int user_key_allowed(struct passwd *pw, Key *key);
|
||||||
|
int
|
||||||
|
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
|
||||||
|
Key *key);
|
||||||
|
|
||||||
/* auth */
|
/* auth */
|
||||||
|
void userauth_banner(void);
|
||||||
|
void userauth_reply(Authctxt *authctxt, int authenticated);
|
||||||
int userauth_none(Authctxt *authctxt);
|
int userauth_none(Authctxt *authctxt);
|
||||||
int userauth_passwd(Authctxt *authctxt);
|
int userauth_passwd(Authctxt *authctxt);
|
||||||
int userauth_pubkey(Authctxt *authctxt);
|
int userauth_pubkey(Authctxt *authctxt);
|
||||||
|
int userauth_hostbased(Authctxt *authctxt);
|
||||||
int userauth_kbdint(Authctxt *authctxt);
|
int userauth_kbdint(Authctxt *authctxt);
|
||||||
|
|
||||||
Authmethod authmethods[] = {
|
Authmethod authmethods[] = {
|
||||||
@ -96,13 +101,16 @@ Authmethod authmethods[] = {
|
|||||||
&one},
|
&one},
|
||||||
{"publickey",
|
{"publickey",
|
||||||
userauth_pubkey,
|
userauth_pubkey,
|
||||||
&options.dsa_authentication},
|
&options.pubkey_authentication},
|
||||||
{"keyboard-interactive",
|
|
||||||
userauth_kbdint,
|
|
||||||
&options.kbd_interactive_authentication},
|
|
||||||
{"password",
|
{"password",
|
||||||
userauth_passwd,
|
userauth_passwd,
|
||||||
&options.password_authentication},
|
&options.password_authentication},
|
||||||
|
{"keyboard-interactive",
|
||||||
|
userauth_kbdint,
|
||||||
|
&options.kbd_interactive_authentication},
|
||||||
|
{"hostbased",
|
||||||
|
userauth_hostbased,
|
||||||
|
&options.hostbased_authentication},
|
||||||
{NULL, NULL, NULL}
|
{NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,21 +121,22 @@ Authmethod authmethods[] = {
|
|||||||
void
|
void
|
||||||
do_authentication2()
|
do_authentication2()
|
||||||
{
|
{
|
||||||
Authctxt *authctxt = xmalloc(sizeof(*authctxt));
|
Authctxt *authctxt = authctxt_new();
|
||||||
memset(authctxt, 'a', sizeof(*authctxt));
|
|
||||||
authctxt->valid = 0;
|
|
||||||
authctxt->attempt = 0;
|
|
||||||
authctxt->success = 0;
|
|
||||||
x_authctxt = authctxt; /*XXX*/
|
x_authctxt = authctxt; /*XXX*/
|
||||||
|
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
/* turn off kerberos, not supported by SSH2 */
|
/* turn off kerberos, not supported by SSH2 */
|
||||||
options.kerberos_authentication = 0;
|
options.kerberos_authentication = 0;
|
||||||
#endif
|
#endif
|
||||||
|
/* challenge-reponse is implemented via keyboard interactive */
|
||||||
|
if (options.challenge_reponse_authentication)
|
||||||
|
options.kbd_interactive_authentication = 1;
|
||||||
|
|
||||||
dispatch_init(&protocol_error);
|
dispatch_init(&protocol_error);
|
||||||
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
|
dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
|
||||||
dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
|
dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
|
||||||
do_authenticated2();
|
do_authenticated(authctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -144,7 +153,7 @@ void
|
|||||||
input_service_request(int type, int plen, void *ctxt)
|
input_service_request(int type, int plen, void *ctxt)
|
||||||
{
|
{
|
||||||
Authctxt *authctxt = ctxt;
|
Authctxt *authctxt = ctxt;
|
||||||
unsigned int len;
|
u_int len;
|
||||||
int accept = 0;
|
int accept = 0;
|
||||||
char *service = packet_get_string(&len);
|
char *service = packet_get_string(&len);
|
||||||
packet_done();
|
packet_done();
|
||||||
@ -178,33 +187,33 @@ input_userauth_request(int type, int plen, void *ctxt)
|
|||||||
{
|
{
|
||||||
Authctxt *authctxt = ctxt;
|
Authctxt *authctxt = ctxt;
|
||||||
Authmethod *m = NULL;
|
Authmethod *m = NULL;
|
||||||
|
char *user, *service, *method, *style = NULL;
|
||||||
int authenticated = 0;
|
int authenticated = 0;
|
||||||
char *user, *service, *method, *authmsg = NULL;
|
|
||||||
#ifdef HAVE_LOGIN_CAP
|
#ifdef HAVE_LOGIN_CAP
|
||||||
login_cap_t *lc;
|
login_cap_t *lc;
|
||||||
#endif /* HAVE_LOGIN_CAP */
|
#endif /* HAVE_LOGIN_CAP */
|
||||||
#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
|
#if defined(HAVE_LOGIN_CAP) || defined(LOGIN_ACCESS)
|
||||||
const char *from_host, *from_ip;
|
const char *from_host, *from_ip;
|
||||||
|
|
||||||
from_host = get_canonical_hostname();
|
from_host = get_canonical_hostname(options.reverse_mapping_check);
|
||||||
from_ip = get_remote_ipaddr();
|
from_ip = get_remote_ipaddr();
|
||||||
#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
|
#endif /* HAVE_LOGIN_CAP || LOGIN_ACCESS */
|
||||||
|
|
||||||
if (authctxt == NULL)
|
if (authctxt == NULL)
|
||||||
fatal("input_userauth_request: no authctxt");
|
fatal("input_userauth_request: no authctxt");
|
||||||
if (authctxt->attempt++ >= AUTH_FAIL_MAX)
|
|
||||||
packet_disconnect("too many failed userauth_requests");
|
|
||||||
|
|
||||||
user = packet_get_string(NULL);
|
user = packet_get_string(NULL);
|
||||||
service = packet_get_string(NULL);
|
service = packet_get_string(NULL);
|
||||||
method = packet_get_string(NULL);
|
method = packet_get_string(NULL);
|
||||||
debug("userauth-request for user %s service %s method %s", user, service, method);
|
debug("userauth-request for user %s service %s method %s", user, service, method);
|
||||||
debug("attempt #%d", authctxt->attempt);
|
debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
|
||||||
|
|
||||||
if (authctxt->attempt == 1) {
|
if ((style = strchr(user, ':')) != NULL)
|
||||||
|
*style++ = 0;
|
||||||
|
|
||||||
|
if (authctxt->attempt++ == 0) {
|
||||||
/* setup auth context */
|
/* setup auth context */
|
||||||
struct passwd *pw = NULL;
|
struct passwd *pw = NULL;
|
||||||
setproctitle("%s", user);
|
|
||||||
pw = getpwnam(user);
|
pw = getpwnam(user);
|
||||||
if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
|
if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
|
||||||
authctxt->pw = pwcopy(pw);
|
authctxt->pw = pwcopy(pw);
|
||||||
@ -217,12 +226,14 @@ input_userauth_request(int type, int plen, void *ctxt)
|
|||||||
log("input_userauth_request: illegal user %s", user);
|
log("input_userauth_request: illegal user %s", user);
|
||||||
authctxt->pw = NULL;
|
authctxt->pw = NULL;
|
||||||
}
|
}
|
||||||
|
setproctitle("%s", pw ? user : "unknown");
|
||||||
authctxt->user = xstrdup(user);
|
authctxt->user = xstrdup(user);
|
||||||
authctxt->service = xstrdup(service);
|
authctxt->service = xstrdup(service);
|
||||||
|
authctxt->style = style ? xstrdup(style) : NULL; /* currently unused */
|
||||||
} else if (authctxt->valid) {
|
} else if (authctxt->valid) {
|
||||||
if (strcmp(user, authctxt->user) != 0 ||
|
if (strcmp(user, authctxt->user) != 0 ||
|
||||||
strcmp(service, authctxt->service) != 0) {
|
strcmp(service, authctxt->service) != 0) {
|
||||||
log("input_userauth_request: missmatch: (%s,%s)!=(%s,%s)",
|
log("input_userauth_request: mismatch: (%s,%s)!=(%s,%s)",
|
||||||
user, service, authctxt->user, authctxt->service);
|
user, service, authctxt->user, authctxt->service);
|
||||||
authctxt->valid = 0;
|
authctxt->valid = 0;
|
||||||
}
|
}
|
||||||
@ -255,79 +266,88 @@ input_userauth_request(int type, int plen, void *ctxt)
|
|||||||
packet_disconnect("Sorry, you are not allowed to connect.");
|
packet_disconnect("Sorry, you are not allowed to connect.");
|
||||||
}
|
}
|
||||||
#endif /* LOGIN_ACCESS */
|
#endif /* LOGIN_ACCESS */
|
||||||
|
/* reset state */
|
||||||
|
dispatch_set(SSH2_MSG_USERAUTH_INFO_RESPONSE, &protocol_error);
|
||||||
|
authctxt->postponed = 0;
|
||||||
|
#ifdef BSD_AUTH
|
||||||
|
if (authctxt->as) {
|
||||||
|
auth_close(authctxt->as);
|
||||||
|
authctxt->as = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* try to authenticate user */
|
||||||
m = authmethod_lookup(method);
|
m = authmethod_lookup(method);
|
||||||
if (m != NULL) {
|
if (m != NULL) {
|
||||||
debug2("input_userauth_request: try method %s", method);
|
debug2("input_userauth_request: try method %s", method);
|
||||||
authenticated = m->userauth(authctxt);
|
authenticated = m->userauth(authctxt);
|
||||||
} else {
|
|
||||||
debug2("input_userauth_request: unsupported method %s", method);
|
|
||||||
}
|
}
|
||||||
if (!authctxt->valid && authenticated == 1) {
|
|
||||||
log("input_userauth_request: INTERNAL ERROR: authenticated invalid user %s service %s", user, method);
|
|
||||||
authenticated = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Special handling for root */
|
|
||||||
if (authenticated == 1 &&
|
|
||||||
authctxt->valid && authctxt->pw->pw_uid == 0 && !options.permit_root_login) {
|
|
||||||
authenticated = 0;
|
|
||||||
log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname());
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
if (authenticated && authctxt->user && !do_pam_account(authctxt->user, NULL))
|
if (authenticated && authctxt->user && !do_pam_account(authctxt->user, NULL))
|
||||||
authenticated = 0;
|
authenticated = 0;
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
|
userauth_finish(authctxt, authenticated, method);
|
||||||
/* Log before sending the reply */
|
|
||||||
userauth_log(authctxt, authenticated, method);
|
|
||||||
userauth_reply(authctxt, authenticated);
|
|
||||||
|
|
||||||
xfree(service);
|
xfree(service);
|
||||||
xfree(user);
|
xfree(user);
|
||||||
xfree(method);
|
xfree(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
userauth_log(Authctxt *authctxt, int authenticated, char *method)
|
userauth_finish(Authctxt *authctxt, int authenticated, char *method)
|
||||||
{
|
{
|
||||||
void (*authlog) (const char *fmt,...) = verbose;
|
if (!authctxt->valid && authenticated)
|
||||||
char *user = NULL, *authmsg = NULL;
|
fatal("INTERNAL ERROR: authenticated invalid user %s",
|
||||||
|
authctxt->user);
|
||||||
|
|
||||||
/* Raise logging level */
|
/* Special handling for root */
|
||||||
if (authenticated == 1 ||
|
if (authenticated && authctxt->pw->pw_uid == 0 &&
|
||||||
!authctxt->valid ||
|
!auth_root_allowed(method))
|
||||||
authctxt->attempt >= AUTH_FAIL_LOG ||
|
authenticated = 0;
|
||||||
strcmp(method, "password") == 0)
|
|
||||||
authlog = log;
|
|
||||||
|
|
||||||
if (authenticated == 1) {
|
/* Log before sending the reply */
|
||||||
authmsg = "Accepted";
|
auth_log(authctxt, authenticated, method, " ssh2");
|
||||||
} else if (authenticated == 0) {
|
|
||||||
authmsg = "Failed";
|
|
||||||
} else {
|
|
||||||
authmsg = "Postponed";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (authctxt->valid) {
|
if (!authctxt->postponed)
|
||||||
user = authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user;
|
userauth_reply(authctxt, authenticated);
|
||||||
} else {
|
|
||||||
user = "NOUSER";
|
|
||||||
}
|
|
||||||
|
|
||||||
authlog("%s %s for %.200s from %.200s port %d ssh2",
|
|
||||||
authmsg,
|
|
||||||
method,
|
|
||||||
user,
|
|
||||||
get_remote_ipaddr(),
|
|
||||||
get_remote_port());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
userauth_reply(Authctxt *authctxt, int authenticated)
|
userauth_reply(Authctxt *authctxt, int authenticated)
|
||||||
{
|
{
|
||||||
|
char *methods;
|
||||||
|
|
||||||
/* XXX todo: check if multiple auth methods are needed */
|
/* XXX todo: check if multiple auth methods are needed */
|
||||||
if (authenticated == 1) {
|
if (authenticated == 1) {
|
||||||
/* turn off userauth */
|
/* turn off userauth */
|
||||||
@ -337,16 +357,16 @@ userauth_reply(Authctxt *authctxt, int authenticated)
|
|||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
/* now we can break out */
|
/* now we can break out */
|
||||||
authctxt->success = 1;
|
authctxt->success = 1;
|
||||||
} else if (authenticated == 0) {
|
} else {
|
||||||
char *methods = authmethods_get();
|
if (authctxt->failures++ > AUTH_FAIL_MAX)
|
||||||
|
packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
|
||||||
|
methods = authmethods_get();
|
||||||
packet_start(SSH2_MSG_USERAUTH_FAILURE);
|
packet_start(SSH2_MSG_USERAUTH_FAILURE);
|
||||||
packet_put_cstring(methods);
|
packet_put_cstring(methods);
|
||||||
packet_put_char(0); /* XXX partial success, unused */
|
packet_put_char(0); /* XXX partial success, unused */
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
xfree(methods);
|
xfree(methods);
|
||||||
} else {
|
|
||||||
/* do nothing, we did already send a reply */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,10 +378,11 @@ userauth_none(Authctxt *authctxt)
|
|||||||
if (m != NULL)
|
if (m != NULL)
|
||||||
m->enabled = NULL;
|
m->enabled = NULL;
|
||||||
packet_done();
|
packet_done();
|
||||||
|
userauth_banner();
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
return authctxt->valid ? auth_pam_password(authctxt->pw, "") : 0;
|
return authctxt->valid ? auth_pam_password(authctxt, "") : 0;
|
||||||
#else /* !USE_PAM */
|
#else /* !USE_PAM */
|
||||||
return authctxt->valid ? auth_password(authctxt->pw, "") : 0;
|
return authctxt->valid ? auth_password(authctxt, "") : 0;
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,7 +392,7 @@ userauth_passwd(Authctxt *authctxt)
|
|||||||
char *password;
|
char *password;
|
||||||
int authenticated = 0;
|
int authenticated = 0;
|
||||||
int change;
|
int change;
|
||||||
unsigned int len;
|
u_int len;
|
||||||
change = packet_get_char();
|
change = packet_get_char();
|
||||||
if (change)
|
if (change)
|
||||||
log("password change not supported");
|
log("password change not supported");
|
||||||
@ -379,9 +400,9 @@ userauth_passwd(Authctxt *authctxt)
|
|||||||
packet_done();
|
packet_done();
|
||||||
if (authctxt->valid &&
|
if (authctxt->valid &&
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
auth_pam_password(authctxt->pw, password) == 1
|
auth_pam_password(authctxt, password) == 1
|
||||||
#else
|
#else
|
||||||
auth_password(authctxt->pw, password) == 1
|
auth_password(authctxt, password) == 1
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
authenticated = 1;
|
authenticated = 1;
|
||||||
@ -402,11 +423,10 @@ userauth_kbdint(Authctxt *authctxt)
|
|||||||
packet_done();
|
packet_done();
|
||||||
|
|
||||||
debug("keyboard-interactive language %s devs %s", lang, devs);
|
debug("keyboard-interactive language %s devs %s", lang, devs);
|
||||||
#ifdef SKEY
|
|
||||||
/* XXX hardcoded, we should look at devs */
|
if (options.challenge_reponse_authentication)
|
||||||
if (options.skey_authentication != 0)
|
authenticated = auth2_challenge(authctxt, devs);
|
||||||
authenticated = auth2_skey(authctxt);
|
|
||||||
#endif
|
|
||||||
xfree(lang);
|
xfree(lang);
|
||||||
xfree(devs);
|
xfree(devs);
|
||||||
return authenticated;
|
return authenticated;
|
||||||
@ -418,8 +438,8 @@ userauth_pubkey(Authctxt *authctxt)
|
|||||||
Buffer b;
|
Buffer b;
|
||||||
Key *key;
|
Key *key;
|
||||||
char *pkalg, *pkblob, *sig;
|
char *pkalg, *pkblob, *sig;
|
||||||
unsigned int alen, blen, slen;
|
u_int alen, blen, slen;
|
||||||
int have_sig;
|
int have_sig, pktype;
|
||||||
int authenticated = 0;
|
int authenticated = 0;
|
||||||
|
|
||||||
if (!authctxt->valid) {
|
if (!authctxt->valid) {
|
||||||
@ -427,14 +447,28 @@ userauth_pubkey(Authctxt *authctxt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
have_sig = packet_get_char();
|
have_sig = packet_get_char();
|
||||||
pkalg = packet_get_string(&alen);
|
if (datafellows & SSH_BUG_PKAUTH) {
|
||||||
if (strcmp(pkalg, KEX_DSS) != 0) {
|
debug2("userauth_pubkey: SSH_BUG_PKAUTH");
|
||||||
log("bad pkalg %s", pkalg); /*XXX*/
|
/* 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);
|
||||||
xfree(pkalg);
|
xfree(pkalg);
|
||||||
|
xfree(pkblob);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pkblob = packet_get_string(&blen);
|
key = key_from_blob(pkblob, blen);
|
||||||
key = dsa_key_from_blob(pkblob, blen);
|
|
||||||
if (key != NULL) {
|
if (key != NULL) {
|
||||||
if (have_sig) {
|
if (have_sig) {
|
||||||
sig = packet_get_string(&slen);
|
sig = packet_get_string(&slen);
|
||||||
@ -449,19 +483,23 @@ userauth_pubkey(Authctxt *authctxt)
|
|||||||
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
|
buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
|
||||||
buffer_put_cstring(&b, authctxt->user);
|
buffer_put_cstring(&b, authctxt->user);
|
||||||
buffer_put_cstring(&b,
|
buffer_put_cstring(&b,
|
||||||
datafellows & SSH_BUG_PUBKEYAUTH ?
|
datafellows & SSH_BUG_PKSERVICE ?
|
||||||
"ssh-userauth" :
|
"ssh-userauth" :
|
||||||
authctxt->service);
|
authctxt->service);
|
||||||
buffer_put_cstring(&b, "publickey");
|
if (datafellows & SSH_BUG_PKAUTH) {
|
||||||
buffer_put_char(&b, have_sig);
|
buffer_put_char(&b, have_sig);
|
||||||
buffer_put_cstring(&b, KEX_DSS);
|
} else {
|
||||||
|
buffer_put_cstring(&b, "publickey");
|
||||||
|
buffer_put_char(&b, have_sig);
|
||||||
|
buffer_put_cstring(&b, pkalg);
|
||||||
|
}
|
||||||
buffer_put_string(&b, pkblob, blen);
|
buffer_put_string(&b, pkblob, blen);
|
||||||
#ifdef DEBUG_DSS
|
#ifdef DEBUG_PK
|
||||||
buffer_dump(&b);
|
buffer_dump(&b);
|
||||||
#endif
|
#endif
|
||||||
/* test for correct signature */
|
/* test for correct signature */
|
||||||
if (user_dsa_key_allowed(authctxt->pw, key) &&
|
if (user_key_allowed(authctxt->pw, key) &&
|
||||||
dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
|
key_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
|
||||||
authenticated = 1;
|
authenticated = 1;
|
||||||
buffer_clear(&b);
|
buffer_clear(&b);
|
||||||
xfree(sig);
|
xfree(sig);
|
||||||
@ -477,24 +515,100 @@ userauth_pubkey(Authctxt *authctxt)
|
|||||||
* if a user is not allowed to login. is this an
|
* if a user is not allowed to login. is this an
|
||||||
* issue? -markus
|
* issue? -markus
|
||||||
*/
|
*/
|
||||||
if (user_dsa_key_allowed(authctxt->pw, key)) {
|
if (user_key_allowed(authctxt->pw, key)) {
|
||||||
packet_start(SSH2_MSG_USERAUTH_PK_OK);
|
packet_start(SSH2_MSG_USERAUTH_PK_OK);
|
||||||
packet_put_string(pkalg, alen);
|
packet_put_string(pkalg, alen);
|
||||||
packet_put_string(pkblob, blen);
|
packet_put_string(pkblob, blen);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
authenticated = -1;
|
authctxt->postponed = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (authenticated != 1)
|
if (authenticated != 1)
|
||||||
auth_clear_options();
|
auth_clear_options();
|
||||||
key_free(key);
|
key_free(key);
|
||||||
}
|
}
|
||||||
|
debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg);
|
||||||
xfree(pkalg);
|
xfree(pkalg);
|
||||||
xfree(pkblob);
|
xfree(pkblob);
|
||||||
return authenticated;
|
return authenticated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
userauth_hostbased(Authctxt *authctxt)
|
||||||
|
{
|
||||||
|
Buffer b;
|
||||||
|
Key *key;
|
||||||
|
char *pkalg, *pkblob, *sig, *cuser, *chost, *service;
|
||||||
|
u_int alen, blen, slen;
|
||||||
|
int pktype;
|
||||||
|
int authenticated = 0;
|
||||||
|
|
||||||
|
if (!authctxt->valid) {
|
||||||
|
debug2("userauth_hostbased: disabled because of invalid user");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pkalg = packet_get_string(&alen);
|
||||||
|
pkblob = packet_get_string(&blen);
|
||||||
|
chost = packet_get_string(NULL);
|
||||||
|
cuser = packet_get_string(NULL);
|
||||||
|
sig = packet_get_string(&slen);
|
||||||
|
|
||||||
|
debug("userauth_hostbased: cuser %s chost %s pkalg %s slen %d",
|
||||||
|
cuser, chost, pkalg, slen);
|
||||||
|
#ifdef DEBUG_PK
|
||||||
|
debug("signature:");
|
||||||
|
buffer_init(&b);
|
||||||
|
buffer_append(&b, sig, slen);
|
||||||
|
buffer_dump(&b);
|
||||||
|
buffer_free(&b);
|
||||||
|
#endif
|
||||||
|
pktype = key_type_from_name(pkalg);
|
||||||
|
if (pktype == KEY_UNSPEC) {
|
||||||
|
/* this is perfectly legal */
|
||||||
|
log("userauth_hostbased: unsupported "
|
||||||
|
"public key algorithm: %s", pkalg);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
key = key_from_blob(pkblob, blen);
|
||||||
|
if (key == NULL) {
|
||||||
|
debug("userauth_hostbased: cannot decode key: %s", pkalg);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
key_free(key);
|
||||||
|
|
||||||
|
done:
|
||||||
|
debug2("userauth_hostbased: authenticated %d", authenticated);
|
||||||
|
xfree(pkalg);
|
||||||
|
xfree(pkblob);
|
||||||
|
xfree(cuser);
|
||||||
|
xfree(chost);
|
||||||
|
xfree(sig);
|
||||||
|
return authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
/* get current user */
|
/* get current user */
|
||||||
|
|
||||||
struct passwd*
|
struct passwd*
|
||||||
@ -509,7 +623,7 @@ char *
|
|||||||
authmethods_get(void)
|
authmethods_get(void)
|
||||||
{
|
{
|
||||||
Authmethod *method = NULL;
|
Authmethod *method = NULL;
|
||||||
unsigned int size = 0;
|
u_int size = 0;
|
||||||
char *list;
|
char *list;
|
||||||
|
|
||||||
for (method = authmethods; method->name != NULL; method++) {
|
for (method = authmethods; method->name != NULL; method++) {
|
||||||
@ -553,13 +667,12 @@ authmethod_lookup(const char *name)
|
|||||||
|
|
||||||
/* return 1 if user allows given key */
|
/* return 1 if user allows given key */
|
||||||
int
|
int
|
||||||
user_dsa_key_allowed(struct passwd *pw, Key *key)
|
user_key_allowed(struct passwd *pw, Key *key)
|
||||||
{
|
{
|
||||||
char line[8192], file[1024];
|
char line[8192], file[MAXPATHLEN];
|
||||||
int found_key = 0;
|
int found_key = 0;
|
||||||
unsigned int bits = -1;
|
|
||||||
FILE *f;
|
FILE *f;
|
||||||
unsigned long linenum = 0;
|
u_long linenum = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
Key *found;
|
Key *found;
|
||||||
|
|
||||||
@ -567,11 +680,11 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Temporarily use the user's uid. */
|
/* Temporarily use the user's uid. */
|
||||||
temporarily_use_uid(pw->pw_uid);
|
temporarily_use_uid(pw);
|
||||||
|
|
||||||
/* The authorized keys. */
|
/* The authorized keys. */
|
||||||
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
|
snprintf(file, sizeof file, "%.500s/%.100s", pw->pw_dir,
|
||||||
SSH_USER_PERMITTED_KEYS2);
|
_PATH_SSH_USER_PERMITTED_KEYS2);
|
||||||
|
|
||||||
/* Fail quietly if file does not exist */
|
/* Fail quietly if file does not exist */
|
||||||
if (stat(file, &st) < 0) {
|
if (stat(file, &st) < 0) {
|
||||||
@ -599,10 +712,10 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||||||
key_type(key), pw->pw_name, file);
|
key_type(key), pw->pw_name, file);
|
||||||
fail = 1;
|
fail = 1;
|
||||||
} else {
|
} else {
|
||||||
/* Check path to SSH_USER_PERMITTED_KEYS */
|
/* Check path to _PATH_SSH_USER_PERMITTED_KEYS */
|
||||||
int i;
|
int i;
|
||||||
static const char *check[] = {
|
static const char *check[] = {
|
||||||
"", SSH_USER_DIR, NULL
|
"", _PATH_SSH_USER_DIR, NULL
|
||||||
};
|
};
|
||||||
for (i = 0; check[i]; i++) {
|
for (i = 0; check[i]; i++) {
|
||||||
snprintf(line, sizeof line, "%.500s/%.100s",
|
snprintf(line, sizeof line, "%.500s/%.100s",
|
||||||
@ -621,7 +734,7 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||||||
}
|
}
|
||||||
if (fail) {
|
if (fail) {
|
||||||
fclose(f);
|
fclose(f);
|
||||||
log("%s",buf);
|
log("%s", buf);
|
||||||
restore_uid();
|
restore_uid();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -638,10 +751,10 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||||||
if (!*cp || *cp == '\n' || *cp == '#')
|
if (!*cp || *cp == '\n' || *cp == '#')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bits = key_read(found, &cp);
|
if (key_read(found, &cp) == -1) {
|
||||||
if (bits == 0) {
|
|
||||||
/* no key? check if there are options for this key */
|
/* no key? check if there are options for this key */
|
||||||
int quoted = 0;
|
int quoted = 0;
|
||||||
|
debug2("user_key_allowed: check options: '%s'", cp);
|
||||||
options = cp;
|
options = cp;
|
||||||
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
|
for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
|
||||||
if (*cp == '\\' && cp[1] == '"')
|
if (*cp == '\\' && cp[1] == '"')
|
||||||
@ -652,14 +765,14 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||||||
/* Skip remaining whitespace. */
|
/* Skip remaining whitespace. */
|
||||||
for (; *cp == ' ' || *cp == '\t'; cp++)
|
for (; *cp == ' ' || *cp == '\t'; cp++)
|
||||||
;
|
;
|
||||||
bits = key_read(found, &cp);
|
if (key_read(found, &cp) == -1) {
|
||||||
if (bits == 0) {
|
debug2("user_key_allowed: advance: '%s'", cp);
|
||||||
/* still no key? advance to next line*/
|
/* still no key? advance to next line*/
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key_equal(found, key) &&
|
if (key_equal(found, key) &&
|
||||||
auth_parse_options(pw, options, linenum) == 1) {
|
auth_parse_options(pw, options, file, linenum) == 1) {
|
||||||
found_key = 1;
|
found_key = 1;
|
||||||
debug("matching key found: file %s, line %ld",
|
debug("matching key found: file %s, line %ld",
|
||||||
file, linenum);
|
file, linenum);
|
||||||
@ -669,22 +782,73 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
|
|||||||
restore_uid();
|
restore_uid();
|
||||||
fclose(f);
|
fclose(f);
|
||||||
key_free(found);
|
key_free(found);
|
||||||
|
if (!found_key)
|
||||||
|
debug2("key not found");
|
||||||
return found_key;
|
return found_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct passwd *
|
/* return 1 if given hostkey is allowed */
|
||||||
pwcopy(struct passwd *pw)
|
int
|
||||||
|
hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
|
||||||
|
Key *key)
|
||||||
{
|
{
|
||||||
struct passwd *copy = xmalloc(sizeof(*copy));
|
Key *found;
|
||||||
memset(copy, 0, sizeof(*copy));
|
const char *resolvedname, *ipaddr, *lookup;
|
||||||
copy->pw_name = xstrdup(pw->pw_name);
|
struct stat st;
|
||||||
copy->pw_passwd = xstrdup(pw->pw_passwd);
|
char *user_hostfile;
|
||||||
copy->pw_uid = pw->pw_uid;
|
int host_status, len;
|
||||||
copy->pw_gid = pw->pw_gid;
|
|
||||||
copy->pw_class = xstrdup(pw->pw_class);
|
resolvedname = get_canonical_hostname(options.reverse_mapping_check);
|
||||||
copy->pw_dir = xstrdup(pw->pw_dir);
|
ipaddr = get_remote_ipaddr();
|
||||||
copy->pw_shell = xstrdup(pw->pw_shell);
|
|
||||||
copy->pw_expire = pw->pw_expire;
|
debug2("userauth_hostbased: chost %s resolvedname %s ipaddr %s",
|
||||||
copy->pw_change = pw->pw_change;
|
chost, resolvedname, ipaddr);
|
||||||
return copy;
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
/* XXX this is copied from auth-rh-rsa.c and should be shared */
|
||||||
|
found = key_new(key->type);
|
||||||
|
host_status = check_host_in_hostfile(_PATH_SSH_SYSTEM_HOSTFILE2, lookup,
|
||||||
|
key, found, NULL);
|
||||||
|
|
||||||
|
if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
|
||||||
|
user_hostfile = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE2,
|
||||||
|
pw->pw_uid);
|
||||||
|
if (options.strict_modes &&
|
||||||
|
(stat(user_hostfile, &st) == 0) &&
|
||||||
|
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
|
||||||
|
(st.st_mode & 022) != 0)) {
|
||||||
|
log("Hostbased authentication refused for %.100s: "
|
||||||
|
"bad owner or modes for %.200s",
|
||||||
|
pw->pw_name, user_hostfile);
|
||||||
|
} else {
|
||||||
|
temporarily_use_uid(pw);
|
||||||
|
host_status = check_host_in_hostfile(user_hostfile,
|
||||||
|
lookup, key, found, NULL);
|
||||||
|
restore_uid();
|
||||||
|
}
|
||||||
|
xfree(user_hostfile);
|
||||||
|
}
|
||||||
|
key_free(found);
|
||||||
|
|
||||||
|
debug2("userauth_hostbased: key %s for %s", host_status == HOST_OK ?
|
||||||
|
"ok" : "not found", lookup);
|
||||||
|
return (host_status == HOST_OK);
|
||||||
}
|
}
|
||||||
|
@ -35,24 +35,24 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: authfd.c,v 1.29 2000/10/09 21:51:00 markus Exp $");
|
RCSID("$OpenBSD: authfd.c,v 1.39 2001/04/05 10:42:48 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "getput.h"
|
#include "getput.h"
|
||||||
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
|
#include "cipher.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "dsa.h"
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "atomicio.h"
|
||||||
|
|
||||||
/* helper */
|
/* helper */
|
||||||
int decode_reply(int type);
|
int decode_reply(int type);
|
||||||
@ -64,7 +64,7 @@ int decode_reply(int type);
|
|||||||
/* Returns the number of the authentication fd, or -1 if there is none. */
|
/* Returns the number of the authentication fd, or -1 if there is none. */
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_get_authentication_socket()
|
ssh_get_authentication_socket(void)
|
||||||
{
|
{
|
||||||
const char *authsocket;
|
const char *authsocket;
|
||||||
int sock, len;
|
int sock, len;
|
||||||
@ -76,7 +76,8 @@ ssh_get_authentication_socket()
|
|||||||
|
|
||||||
sunaddr.sun_family = AF_UNIX;
|
sunaddr.sun_family = AF_UNIX;
|
||||||
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
|
strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
|
||||||
sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1;
|
len = SUN_LEN(&sunaddr)+1;
|
||||||
|
sunaddr.sun_len = len;
|
||||||
|
|
||||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
@ -118,6 +119,8 @@ ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply
|
|||||||
len = 4;
|
len = 4;
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
l = read(auth->fd, buf + 4 - len, len);
|
l = read(auth->fd, buf + 4 - len, len);
|
||||||
|
if (l == -1 && (errno == EAGAIN || errno == EINTR))
|
||||||
|
continue;
|
||||||
if (l <= 0) {
|
if (l <= 0) {
|
||||||
error("Error reading response length from authentication socket.");
|
error("Error reading response length from authentication socket.");
|
||||||
return 0;
|
return 0;
|
||||||
@ -137,6 +140,8 @@ ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply
|
|||||||
if (l > sizeof(buf))
|
if (l > sizeof(buf))
|
||||||
l = sizeof(buf);
|
l = sizeof(buf);
|
||||||
l = read(auth->fd, buf, l);
|
l = read(auth->fd, buf, l);
|
||||||
|
if (l == -1 && (errno == EAGAIN || errno == EINTR))
|
||||||
|
continue;
|
||||||
if (l <= 0) {
|
if (l <= 0) {
|
||||||
error("Error reading response from authentication socket.");
|
error("Error reading response from authentication socket.");
|
||||||
return 0;
|
return 0;
|
||||||
@ -169,7 +174,7 @@ ssh_close_authentication_socket(int sock)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
AuthenticationConnection *
|
AuthenticationConnection *
|
||||||
ssh_get_authentication_connection()
|
ssh_get_authentication_connection(void)
|
||||||
{
|
{
|
||||||
AuthenticationConnection *auth;
|
AuthenticationConnection *auth;
|
||||||
int sock;
|
int sock;
|
||||||
@ -208,8 +213,8 @@ ssh_close_authentication_connection(AuthenticationConnection *auth)
|
|||||||
* Returns the first authentication identity held by the agent.
|
* Returns the first authentication identity held by the agent.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Key *
|
int
|
||||||
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
|
ssh_get_num_identities(AuthenticationConnection *auth, int version)
|
||||||
{
|
{
|
||||||
int type, code1 = 0, code2 = 0;
|
int type, code1 = 0, code2 = 0;
|
||||||
Buffer request;
|
Buffer request;
|
||||||
@ -224,7 +229,7 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
|
|||||||
code2 = SSH2_AGENT_IDENTITIES_ANSWER;
|
code2 = SSH2_AGENT_IDENTITIES_ANSWER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -237,14 +242,14 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
|
|||||||
buffer_clear(&auth->identities);
|
buffer_clear(&auth->identities);
|
||||||
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
|
if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
|
||||||
buffer_free(&request);
|
buffer_free(&request);
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
buffer_free(&request);
|
buffer_free(&request);
|
||||||
|
|
||||||
/* Get message type, and verify that we got a proper answer. */
|
/* Get message type, and verify that we got a proper answer. */
|
||||||
type = buffer_get_char(&auth->identities);
|
type = buffer_get_char(&auth->identities);
|
||||||
if (agent_failed(type)) {
|
if (agent_failed(type)) {
|
||||||
return NULL;
|
return 0;
|
||||||
} else if (type != code2) {
|
} else if (type != code2) {
|
||||||
fatal("Bad authentication reply message type: %d", type);
|
fatal("Bad authentication reply message type: %d", type);
|
||||||
}
|
}
|
||||||
@ -252,19 +257,27 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
|
|||||||
/* Get the number of entries in the response and check it for sanity. */
|
/* Get the number of entries in the response and check it for sanity. */
|
||||||
auth->howmany = buffer_get_int(&auth->identities);
|
auth->howmany = buffer_get_int(&auth->identities);
|
||||||
if (auth->howmany > 1024)
|
if (auth->howmany > 1024)
|
||||||
fatal("Too many identities in authentication reply: %d\n",
|
fatal("Too many identities in authentication reply: %d",
|
||||||
auth->howmany);
|
auth->howmany);
|
||||||
|
|
||||||
/* Return the first entry (if any). */
|
return auth->howmany;
|
||||||
return ssh_get_next_identity(auth, comment, version);
|
}
|
||||||
|
|
||||||
|
Key *
|
||||||
|
ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
|
||||||
|
{
|
||||||
|
/* get number of identities and return the first entry (if any). */
|
||||||
|
if (ssh_get_num_identities(auth, version) > 0)
|
||||||
|
return ssh_get_next_identity(auth, comment, version);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key *
|
Key *
|
||||||
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
|
ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
|
||||||
{
|
{
|
||||||
unsigned int bits;
|
u_int bits;
|
||||||
unsigned char *blob;
|
u_char *blob;
|
||||||
unsigned int blen;
|
u_int blen;
|
||||||
Key *key = NULL;
|
Key *key = NULL;
|
||||||
|
|
||||||
/* Return failure if no more entries. */
|
/* Return failure if no more entries. */
|
||||||
@ -277,7 +290,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
|
|||||||
*/
|
*/
|
||||||
switch(version){
|
switch(version){
|
||||||
case 1:
|
case 1:
|
||||||
key = key_new(KEY_RSA);
|
key = key_new(KEY_RSA1);
|
||||||
bits = buffer_get_int(&auth->identities);
|
bits = buffer_get_int(&auth->identities);
|
||||||
buffer_get_bignum(&auth->identities, key->rsa->e);
|
buffer_get_bignum(&auth->identities, key->rsa->e);
|
||||||
buffer_get_bignum(&auth->identities, key->rsa->n);
|
buffer_get_bignum(&auth->identities, key->rsa->n);
|
||||||
@ -289,7 +302,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
|
|||||||
case 2:
|
case 2:
|
||||||
blob = buffer_get_string(&auth->identities, &blen);
|
blob = buffer_get_string(&auth->identities, &blen);
|
||||||
*comment = buffer_get_string(&auth->identities, NULL);
|
*comment = buffer_get_string(&auth->identities, NULL);
|
||||||
key = dsa_key_from_blob(blob, blen);
|
key = key_from_blob(blob, blen);
|
||||||
xfree(blob);
|
xfree(blob);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -312,16 +325,16 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
|
|||||||
int
|
int
|
||||||
ssh_decrypt_challenge(AuthenticationConnection *auth,
|
ssh_decrypt_challenge(AuthenticationConnection *auth,
|
||||||
Key* key, BIGNUM *challenge,
|
Key* key, BIGNUM *challenge,
|
||||||
unsigned char session_id[16],
|
u_char session_id[16],
|
||||||
unsigned int response_type,
|
u_int response_type,
|
||||||
unsigned char response[16])
|
u_char response[16])
|
||||||
{
|
{
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
int success = 0;
|
int success = 0;
|
||||||
int i;
|
int i;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
if (key->type != KEY_RSA)
|
if (key->type != KEY_RSA1)
|
||||||
return 0;
|
return 0;
|
||||||
if (response_type == 0) {
|
if (response_type == 0) {
|
||||||
log("Compatibility with ssh protocol version 1.0 no longer supported.");
|
log("Compatibility with ssh protocol version 1.0 no longer supported.");
|
||||||
@ -363,17 +376,17 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
|
|||||||
int
|
int
|
||||||
ssh_agent_sign(AuthenticationConnection *auth,
|
ssh_agent_sign(AuthenticationConnection *auth,
|
||||||
Key *key,
|
Key *key,
|
||||||
unsigned char **sigp, int *lenp,
|
u_char **sigp, int *lenp,
|
||||||
unsigned char *data, int datalen)
|
u_char *data, int datalen)
|
||||||
{
|
{
|
||||||
extern int datafellows;
|
extern int datafellows;
|
||||||
Buffer msg;
|
Buffer msg;
|
||||||
unsigned char *blob;
|
u_char *blob;
|
||||||
unsigned int blen;
|
u_int blen;
|
||||||
int type, flags = 0;
|
int type, flags = 0;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (dsa_make_key_blob(key, &blob, &blen) == 0)
|
if (key_to_blob(key, &blob, &blen) == 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (datafellows & SSH_BUG_SIGBLOB)
|
if (datafellows & SSH_BUG_SIGBLOB)
|
||||||
@ -406,7 +419,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
|
|||||||
/* Encode key for a message to the agent. */
|
/* Encode key for a message to the agent. */
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
|
ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
|
||||||
{
|
{
|
||||||
buffer_clear(b);
|
buffer_clear(b);
|
||||||
buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
|
buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
|
||||||
@ -422,17 +435,29 @@ ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
|
ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
|
||||||
{
|
{
|
||||||
buffer_clear(b);
|
buffer_clear(b);
|
||||||
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
|
buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
|
||||||
buffer_put_cstring(b, KEX_DSS);
|
buffer_put_cstring(b, key_ssh_name(key));
|
||||||
buffer_put_bignum2(b, key->p);
|
switch(key->type){
|
||||||
buffer_put_bignum2(b, key->q);
|
case KEY_RSA:
|
||||||
buffer_put_bignum2(b, key->g);
|
buffer_put_bignum2(b, key->rsa->n);
|
||||||
buffer_put_bignum2(b, key->pub_key);
|
buffer_put_bignum2(b, key->rsa->e);
|
||||||
buffer_put_bignum2(b, key->priv_key);
|
buffer_put_bignum2(b, key->rsa->d);
|
||||||
buffer_put_string(b, comment, strlen(comment));
|
buffer_put_bignum2(b, key->rsa->iqmp);
|
||||||
|
buffer_put_bignum2(b, key->rsa->p);
|
||||||
|
buffer_put_bignum2(b, key->rsa->q);
|
||||||
|
break;
|
||||||
|
case KEY_DSA:
|
||||||
|
buffer_put_bignum2(b, key->dsa->p);
|
||||||
|
buffer_put_bignum2(b, key->dsa->q);
|
||||||
|
buffer_put_bignum2(b, key->dsa->g);
|
||||||
|
buffer_put_bignum2(b, key->dsa->pub_key);
|
||||||
|
buffer_put_bignum2(b, key->dsa->priv_key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buffer_put_cstring(b, comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -449,11 +474,12 @@ ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
|
|||||||
buffer_init(&msg);
|
buffer_init(&msg);
|
||||||
|
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case KEY_RSA:
|
case KEY_RSA1:
|
||||||
ssh_encode_identity_rsa(&msg, key->rsa, comment);
|
ssh_encode_identity_rsa1(&msg, key->rsa, comment);
|
||||||
break;
|
break;
|
||||||
|
case KEY_RSA:
|
||||||
case KEY_DSA:
|
case KEY_DSA:
|
||||||
ssh_encode_identity_dsa(&msg, key->dsa, comment);
|
ssh_encode_identity_ssh2(&msg, key, comment);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buffer_free(&msg);
|
buffer_free(&msg);
|
||||||
@ -479,18 +505,18 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
|
|||||||
{
|
{
|
||||||
Buffer msg;
|
Buffer msg;
|
||||||
int type;
|
int type;
|
||||||
unsigned char *blob;
|
u_char *blob;
|
||||||
unsigned int blen;
|
u_int blen;
|
||||||
|
|
||||||
buffer_init(&msg);
|
buffer_init(&msg);
|
||||||
|
|
||||||
if (key->type == KEY_RSA) {
|
if (key->type == KEY_RSA1) {
|
||||||
buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
|
buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
|
||||||
buffer_put_int(&msg, BN_num_bits(key->rsa->n));
|
buffer_put_int(&msg, BN_num_bits(key->rsa->n));
|
||||||
buffer_put_bignum(&msg, key->rsa->e);
|
buffer_put_bignum(&msg, key->rsa->e);
|
||||||
buffer_put_bignum(&msg, key->rsa->n);
|
buffer_put_bignum(&msg, key->rsa->n);
|
||||||
} else if (key->type == KEY_DSA) {
|
} else if (key->type == KEY_DSA || key->type == KEY_RSA) {
|
||||||
dsa_make_key_blob(key, &blob, &blen);
|
key_to_blob(key, &blob, &blen);
|
||||||
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
|
buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
|
||||||
buffer_put_string(&msg, blob, blen);
|
buffer_put_string(&msg, blob, blen);
|
||||||
xfree(blob);
|
xfree(blob);
|
||||||
@ -533,7 +559,7 @@ ssh_remove_all_identities(AuthenticationConnection *auth, int version)
|
|||||||
return decode_reply(type);
|
return decode_reply(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
decode_reply(int type)
|
decode_reply(int type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -36,23 +36,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: authfile.c,v 1.20 2000/10/11 20:27:23 markus Exp $");
|
RCSID("$OpenBSD: authfile.c,v 1.32 2001/04/18 23:44:51 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
|
||||||
|
#include "cipher.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
#include "ssh.h"
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
|
#include "ssh.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "authfile.h"
|
||||||
|
|
||||||
/* Version identification string for identity files. */
|
/* Version identification string for SSH v1 identity files. */
|
||||||
#define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n"
|
static const char authfile_id_string[] =
|
||||||
|
"SSH PRIVATE KEY FILE FORMAT 1.1\n";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Saves the authentication (private) key in a file, encrypting it with
|
* Saves the authentication (private) key in a file, encrypting it with
|
||||||
@ -62,8 +64,8 @@ RCSID("$FreeBSD$");
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
save_private_key_rsa(const char *filename, const char *passphrase,
|
key_save_private_rsa1(Key *key, const char *filename, const char *passphrase,
|
||||||
RSA *key, const char *comment)
|
const char *comment)
|
||||||
{
|
{
|
||||||
Buffer buffer, encrypted;
|
Buffer buffer, encrypted;
|
||||||
char buf[100], *cp;
|
char buf[100], *cp;
|
||||||
@ -99,10 +101,10 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
|||||||
* will be stored in plain text, and storing them also in encrypted
|
* will be stored in plain text, and storing them also in encrypted
|
||||||
* format would just give known plaintext).
|
* format would just give known plaintext).
|
||||||
*/
|
*/
|
||||||
buffer_put_bignum(&buffer, key->d);
|
buffer_put_bignum(&buffer, key->rsa->d);
|
||||||
buffer_put_bignum(&buffer, key->iqmp);
|
buffer_put_bignum(&buffer, key->rsa->iqmp);
|
||||||
buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */
|
buffer_put_bignum(&buffer, key->rsa->q); /* reverse from SSL p */
|
||||||
buffer_put_bignum(&buffer, key->p); /* reverse from SSL q */
|
buffer_put_bignum(&buffer, key->rsa->p); /* reverse from SSL q */
|
||||||
|
|
||||||
/* Pad the part to be encrypted until its size is a multiple of 8. */
|
/* Pad the part to be encrypted until its size is a multiple of 8. */
|
||||||
while (buffer_len(&buffer) % 8 != 0)
|
while (buffer_len(&buffer) % 8 != 0)
|
||||||
@ -112,9 +114,8 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
|||||||
buffer_init(&encrypted);
|
buffer_init(&encrypted);
|
||||||
|
|
||||||
/* First store keyfile id string. */
|
/* First store keyfile id string. */
|
||||||
cp = AUTHFILE_ID_STRING;
|
for (i = 0; authfile_id_string[i]; i++)
|
||||||
for (i = 0; cp[i]; i++)
|
buffer_put_char(&encrypted, authfile_id_string[i]);
|
||||||
buffer_put_char(&encrypted, cp[i]);
|
|
||||||
buffer_put_char(&encrypted, 0);
|
buffer_put_char(&encrypted, 0);
|
||||||
|
|
||||||
/* Store cipher type. */
|
/* Store cipher type. */
|
||||||
@ -122,17 +123,17 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
|||||||
buffer_put_int(&encrypted, 0); /* For future extension */
|
buffer_put_int(&encrypted, 0); /* For future extension */
|
||||||
|
|
||||||
/* Store public key. This will be in plain text. */
|
/* Store public key. This will be in plain text. */
|
||||||
buffer_put_int(&encrypted, BN_num_bits(key->n));
|
buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
|
||||||
buffer_put_bignum(&encrypted, key->n);
|
buffer_put_bignum(&encrypted, key->rsa->n);
|
||||||
buffer_put_bignum(&encrypted, key->e);
|
buffer_put_bignum(&encrypted, key->rsa->e);
|
||||||
buffer_put_string(&encrypted, comment, strlen(comment));
|
buffer_put_string(&encrypted, comment, strlen(comment));
|
||||||
|
|
||||||
/* Allocate space for the private part of the key in the buffer. */
|
/* Allocate space for the private part of the key in the buffer. */
|
||||||
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
|
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
|
||||||
|
|
||||||
cipher_set_key_string(&ciphercontext, cipher, passphrase);
|
cipher_set_key_string(&ciphercontext, cipher, passphrase);
|
||||||
cipher_encrypt(&ciphercontext, (unsigned char *) cp,
|
cipher_encrypt(&ciphercontext, (u_char *) cp,
|
||||||
(unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
|
(u_char *) buffer_ptr(&buffer), buffer_len(&buffer));
|
||||||
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
||||||
|
|
||||||
/* Destroy temporary data. */
|
/* Destroy temporary data. */
|
||||||
@ -140,15 +141,17 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
|||||||
buffer_free(&buffer);
|
buffer_free(&buffer);
|
||||||
|
|
||||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||||
if (fd < 0)
|
if (fd < 0) {
|
||||||
|
error("open %s failed: %s.", filename, strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
|
if (write(fd, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
|
||||||
buffer_len(&encrypted)) {
|
buffer_len(&encrypted)) {
|
||||||
debug("Write to key file %.200s failed: %.100s", filename,
|
error("write to key file %s failed: %s", filename,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
buffer_free(&encrypted);
|
buffer_free(&encrypted);
|
||||||
close(fd);
|
close(fd);
|
||||||
remove(filename);
|
unlink(filename);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
@ -156,80 +159,168 @@ save_private_key_rsa(const char *filename, const char *passphrase,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* save DSA key in OpenSSL PEM format */
|
/* save SSH v2 key in OpenSSL PEM format */
|
||||||
|
|
||||||
int
|
int
|
||||||
save_private_key_dsa(const char *filename, const char *passphrase,
|
key_save_private_pem(Key *key, const char *filename, const char *_passphrase,
|
||||||
DSA *dsa, const char *comment)
|
const char *comment)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int fd;
|
int fd;
|
||||||
int success = 1;
|
int success = 0;
|
||||||
int len = strlen(passphrase);
|
int len = strlen(_passphrase);
|
||||||
|
char *passphrase = (len > 0) ? (char *)_passphrase : NULL;
|
||||||
|
EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
|
||||||
|
|
||||||
if (len > 0 && len <= 4) {
|
if (len > 0 && len <= 4) {
|
||||||
error("passphrase too short: %d bytes", len);
|
error("passphrase too short: have %d bytes, need > 4", len);
|
||||||
errno = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
debug("open %s failed", filename);
|
error("open %s failed: %s.", filename, strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fp = fdopen(fd, "w");
|
fp = fdopen(fd, "w");
|
||||||
if (fp == NULL ) {
|
if (fp == NULL ) {
|
||||||
debug("fdopen %s failed", filename);
|
error("fdopen %s failed: %s.", filename, strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (len > 0) {
|
switch (key->type) {
|
||||||
if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(),
|
case KEY_DSA:
|
||||||
(char *)passphrase, strlen(passphrase), NULL, NULL))
|
success = PEM_write_DSAPrivateKey(fp, key->dsa,
|
||||||
success = 0;
|
cipher, passphrase, len, NULL, NULL);
|
||||||
} else {
|
break;
|
||||||
if (!PEM_write_DSAPrivateKey(fp, dsa, NULL,
|
case KEY_RSA:
|
||||||
NULL, 0, NULL, NULL))
|
success = PEM_write_RSAPrivateKey(fp, key->rsa,
|
||||||
success = 0;
|
cipher, passphrase, len, NULL, NULL);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
save_private_key(const char *filename, const char *passphrase, Key *key,
|
key_save_private(Key *key, const char *filename, const char *passphrase,
|
||||||
const char *comment)
|
const char *comment)
|
||||||
{
|
{
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case KEY_RSA:
|
case KEY_RSA1:
|
||||||
return save_private_key_rsa(filename, passphrase, key->rsa, comment);
|
return key_save_private_rsa1(key, filename, passphrase,
|
||||||
|
comment);
|
||||||
break;
|
break;
|
||||||
case KEY_DSA:
|
case KEY_DSA:
|
||||||
return save_private_key_dsa(filename, passphrase, key->dsa, comment);
|
case KEY_RSA:
|
||||||
|
return key_save_private_pem(key, filename, passphrase,
|
||||||
|
comment);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
error("key_save_private: cannot save key type %d", key->type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Loads the public part of the key file. Returns 0 if an error was
|
* Loads the public part of the ssh v1 key file. Returns NULL if an error was
|
||||||
* encountered (the file does not exist or is not readable), and non-zero
|
* encountered (the file does not exist or is not readable), and the key
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
Key *
|
||||||
load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
|
key_load_public_rsa1(int fd, const char *filename, char **commentp)
|
||||||
{
|
{
|
||||||
int fd, i;
|
|
||||||
off_t len;
|
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
|
Key *pub;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
int i;
|
||||||
|
off_t len;
|
||||||
|
|
||||||
|
len = lseek(fd, (off_t) 0, SEEK_END);
|
||||||
|
lseek(fd, (off_t) 0, SEEK_SET);
|
||||||
|
|
||||||
|
buffer_init(&buffer);
|
||||||
|
buffer_append_space(&buffer, &cp, len);
|
||||||
|
|
||||||
|
if (read(fd, cp, (size_t) len) != (size_t) len) {
|
||||||
|
debug("Read from key file %.200s failed: %.100s", filename,
|
||||||
|
strerror(errno));
|
||||||
|
buffer_free(&buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that it is at least big enough to contain the ID string. */
|
||||||
|
if (len < sizeof(authfile_id_string)) {
|
||||||
|
debug3("No RSA1 key file %.200s.", filename);
|
||||||
|
buffer_free(&buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Make sure it begins with the id string. Consume the id string
|
||||||
|
* from the buffer.
|
||||||
|
*/
|
||||||
|
for (i = 0; i < sizeof(authfile_id_string); i++)
|
||||||
|
if (buffer_get_char(&buffer) != authfile_id_string[i]) {
|
||||||
|
debug3("No RSA1 key file %.200s.", filename);
|
||||||
|
buffer_free(&buffer);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* Skip cipher type and reserved data. */
|
||||||
|
(void) buffer_get_char(&buffer); /* cipher type */
|
||||||
|
(void) buffer_get_int(&buffer); /* reserved */
|
||||||
|
|
||||||
|
/* Read the public key from the buffer. */
|
||||||
|
buffer_get_int(&buffer);
|
||||||
|
pub = key_new(KEY_RSA1);
|
||||||
|
buffer_get_bignum(&buffer, pub->rsa->n);
|
||||||
|
buffer_get_bignum(&buffer, pub->rsa->e);
|
||||||
|
if (commentp)
|
||||||
|
*commentp = buffer_get_string(&buffer, NULL);
|
||||||
|
/* The encrypted private part is not parsed by this function. */
|
||||||
|
|
||||||
|
buffer_free(&buffer);
|
||||||
|
return pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load public key from private-key file, works only for SSH v1 */
|
||||||
|
Key *
|
||||||
|
key_load_public_type(int type, const char *filename, char **commentp)
|
||||||
|
{
|
||||||
|
Key *pub;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (type == KEY_RSA1) {
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return NULL;
|
||||||
|
pub = key_load_public_rsa1(fd, filename, commentp);
|
||||||
|
close(fd);
|
||||||
|
return pub;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loads the private key from the file. Returns 0 if an error is encountered
|
||||||
|
* (file does not exist or is not readable, or passphrase is bad). This
|
||||||
|
* initializes the private key.
|
||||||
|
* Assumes we are called under uid of the owner of the file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
Key *
|
||||||
|
key_load_private_rsa1(int fd, const char *filename, const char *passphrase,
|
||||||
|
char **commentp)
|
||||||
|
{
|
||||||
|
int i, check1, check2, cipher_type;
|
||||||
|
off_t len;
|
||||||
|
Buffer buffer, decrypted;
|
||||||
|
char *cp;
|
||||||
|
CipherContext ciphercontext;
|
||||||
|
Cipher *cipher;
|
||||||
|
BN_CTX *ctx;
|
||||||
|
BIGNUM *aux;
|
||||||
|
Key *prv = NULL;
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY);
|
|
||||||
if (fd < 0)
|
|
||||||
return 0;
|
|
||||||
len = lseek(fd, (off_t) 0, SEEK_END);
|
len = lseek(fd, (off_t) 0, SEEK_END);
|
||||||
lseek(fd, (off_t) 0, SEEK_SET);
|
lseek(fd, (off_t) 0, SEEK_SET);
|
||||||
|
|
||||||
@ -241,127 +332,40 @@ load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
|
|||||||
strerror(errno));
|
strerror(errno));
|
||||||
buffer_free(&buffer);
|
buffer_free(&buffer);
|
||||||
close(fd);
|
close(fd);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/* Check that it is at least big enought to contain the ID string. */
|
/* Check that it is at least big enough to contain the ID string. */
|
||||||
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
|
if (len < sizeof(authfile_id_string)) {
|
||||||
debug("Bad key file %.200s.", filename);
|
debug3("No RSA1 key file %.200s.", filename);
|
||||||
buffer_free(&buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Make sure it begins with the id string. Consume the id string
|
|
||||||
* from the buffer.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
|
|
||||||
if (buffer_get_char(&buffer) != (u_char) AUTHFILE_ID_STRING[i]) {
|
|
||||||
debug("Bad key file %.200s.", filename);
|
|
||||||
buffer_free(&buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Skip cipher type and reserved data. */
|
|
||||||
(void) buffer_get_char(&buffer); /* cipher type */
|
|
||||||
(void) buffer_get_int(&buffer); /* reserved */
|
|
||||||
|
|
||||||
/* Read the public key from the buffer. */
|
|
||||||
buffer_get_int(&buffer);
|
|
||||||
/* XXX alloc */
|
|
||||||
if (pub->n == NULL)
|
|
||||||
pub->n = BN_new();
|
|
||||||
buffer_get_bignum(&buffer, pub->n);
|
|
||||||
/* XXX alloc */
|
|
||||||
if (pub->e == NULL)
|
|
||||||
pub->e = BN_new();
|
|
||||||
buffer_get_bignum(&buffer, pub->e);
|
|
||||||
if (comment_return)
|
|
||||||
*comment_return = buffer_get_string(&buffer, NULL);
|
|
||||||
/* The encrypted private part is not parsed by this function. */
|
|
||||||
|
|
||||||
buffer_free(&buffer);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load public key from private-key file */
|
|
||||||
int
|
|
||||||
load_public_key(const char *filename, Key * key, char **comment_return)
|
|
||||||
{
|
|
||||||
switch (key->type) {
|
|
||||||
case KEY_RSA:
|
|
||||||
return load_public_key_rsa(filename, key->rsa, comment_return);
|
|
||||||
break;
|
|
||||||
case KEY_DSA:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loads the private key from the file. Returns 0 if an error is encountered
|
|
||||||
* (file does not exist or is not readable, or passphrase is bad). This
|
|
||||||
* initializes the private key.
|
|
||||||
* Assumes we are called under uid of the owner of the file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
load_private_key_rsa(int fd, const char *filename,
|
|
||||||
const char *passphrase, RSA * prv, char **comment_return)
|
|
||||||
{
|
|
||||||
int i, check1, check2, cipher_type;
|
|
||||||
off_t len;
|
|
||||||
Buffer buffer, decrypted;
|
|
||||||
char *cp;
|
|
||||||
CipherContext ciphercontext;
|
|
||||||
Cipher *cipher;
|
|
||||||
BN_CTX *ctx;
|
|
||||||
BIGNUM *aux;
|
|
||||||
|
|
||||||
len = lseek(fd, (off_t) 0, SEEK_END);
|
|
||||||
lseek(fd, (off_t) 0, SEEK_SET);
|
|
||||||
|
|
||||||
buffer_init(&buffer);
|
|
||||||
buffer_append_space(&buffer, &cp, len);
|
|
||||||
|
|
||||||
if (read(fd, cp, (size_t) len) != (size_t) len) {
|
|
||||||
debug("Read from key file %.200s failed: %.100s", filename,
|
|
||||||
strerror(errno));
|
|
||||||
buffer_free(&buffer);
|
buffer_free(&buffer);
|
||||||
close(fd);
|
close(fd);
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
/* Check that it is at least big enought to contain the ID string. */
|
|
||||||
if (len < strlen(AUTHFILE_ID_STRING) + 1) {
|
|
||||||
debug("Bad key file %.200s.", filename);
|
|
||||||
buffer_free(&buffer);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Make sure it begins with the id string. Consume the id string
|
* Make sure it begins with the id string. Consume the id string
|
||||||
* from the buffer.
|
* from the buffer.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
|
for (i = 0; i < sizeof(authfile_id_string); i++)
|
||||||
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
|
if (buffer_get_char(&buffer) != authfile_id_string[i]) {
|
||||||
debug("Bad key file %.200s.", filename);
|
debug3("No RSA1 key file %.200s.", filename);
|
||||||
buffer_free(&buffer);
|
buffer_free(&buffer);
|
||||||
return 0;
|
close(fd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read cipher type. */
|
/* Read cipher type. */
|
||||||
cipher_type = buffer_get_char(&buffer);
|
cipher_type = buffer_get_char(&buffer);
|
||||||
(void) buffer_get_int(&buffer); /* Reserved data. */
|
(void) buffer_get_int(&buffer); /* Reserved data. */
|
||||||
|
|
||||||
/* Read the public key from the buffer. */
|
/* Read the public key from the buffer. */
|
||||||
buffer_get_int(&buffer);
|
buffer_get_int(&buffer);
|
||||||
prv->n = BN_new();
|
prv = key_new_private(KEY_RSA1);
|
||||||
buffer_get_bignum(&buffer, prv->n);
|
|
||||||
prv->e = BN_new();
|
buffer_get_bignum(&buffer, prv->rsa->n);
|
||||||
buffer_get_bignum(&buffer, prv->e);
|
buffer_get_bignum(&buffer, prv->rsa->e);
|
||||||
if (comment_return)
|
if (commentp)
|
||||||
*comment_return = buffer_get_string(&buffer, NULL);
|
*commentp = buffer_get_string(&buffer, NULL);
|
||||||
else
|
else
|
||||||
xfree(buffer_get_string(&buffer, NULL));
|
xfree(buffer_get_string(&buffer, NULL));
|
||||||
|
|
||||||
@ -379,8 +383,8 @@ load_private_key_rsa(int fd, const char *filename,
|
|||||||
|
|
||||||
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
|
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
|
||||||
cipher_set_key_string(&ciphercontext, cipher, passphrase);
|
cipher_set_key_string(&ciphercontext, cipher, passphrase);
|
||||||
cipher_decrypt(&ciphercontext, (unsigned char *) cp,
|
cipher_decrypt(&ciphercontext, (u_char *) cp,
|
||||||
(unsigned char *) buffer_ptr(&buffer), buffer_len(&buffer));
|
(u_char *) buffer_ptr(&buffer), buffer_len(&buffer));
|
||||||
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
memset(&ciphercontext, 0, sizeof(ciphercontext));
|
||||||
buffer_free(&buffer);
|
buffer_free(&buffer);
|
||||||
|
|
||||||
@ -389,138 +393,183 @@ load_private_key_rsa(int fd, const char *filename,
|
|||||||
if (check1 != buffer_get_char(&decrypted) ||
|
if (check1 != buffer_get_char(&decrypted) ||
|
||||||
check2 != buffer_get_char(&decrypted)) {
|
check2 != buffer_get_char(&decrypted)) {
|
||||||
if (strcmp(passphrase, "") != 0)
|
if (strcmp(passphrase, "") != 0)
|
||||||
debug("Bad passphrase supplied for key file %.200s.", filename);
|
debug("Bad passphrase supplied for key file %.200s.",
|
||||||
|
filename);
|
||||||
/* Bad passphrase. */
|
/* Bad passphrase. */
|
||||||
buffer_free(&decrypted);
|
buffer_free(&decrypted);
|
||||||
fail:
|
goto fail;
|
||||||
BN_clear_free(prv->n);
|
|
||||||
prv->n = NULL;
|
|
||||||
BN_clear_free(prv->e);
|
|
||||||
prv->e = NULL;
|
|
||||||
if (comment_return)
|
|
||||||
xfree(*comment_return);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
/* Read the rest of the private key. */
|
/* Read the rest of the private key. */
|
||||||
prv->d = BN_new();
|
buffer_get_bignum(&decrypted, prv->rsa->d);
|
||||||
buffer_get_bignum(&decrypted, prv->d);
|
buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */
|
||||||
prv->iqmp = BN_new();
|
/* in SSL and SSH v1 p and q are exchanged */
|
||||||
buffer_get_bignum(&decrypted, prv->iqmp); /* u */
|
buffer_get_bignum(&decrypted, prv->rsa->q); /* p */
|
||||||
/* in SSL and SSH p and q are exchanged */
|
buffer_get_bignum(&decrypted, prv->rsa->p); /* q */
|
||||||
prv->q = BN_new();
|
|
||||||
buffer_get_bignum(&decrypted, prv->q); /* p */
|
|
||||||
prv->p = BN_new();
|
|
||||||
buffer_get_bignum(&decrypted, prv->p); /* q */
|
|
||||||
|
|
||||||
|
/* calculate p-1 and q-1 */
|
||||||
ctx = BN_CTX_new();
|
ctx = BN_CTX_new();
|
||||||
aux = BN_new();
|
aux = BN_new();
|
||||||
|
|
||||||
BN_sub(aux, prv->q, BN_value_one());
|
BN_sub(aux, prv->rsa->q, BN_value_one());
|
||||||
prv->dmq1 = BN_new();
|
BN_mod(prv->rsa->dmq1, prv->rsa->d, aux, ctx);
|
||||||
BN_mod(prv->dmq1, prv->d, aux, ctx);
|
|
||||||
|
|
||||||
BN_sub(aux, prv->p, BN_value_one());
|
BN_sub(aux, prv->rsa->p, BN_value_one());
|
||||||
prv->dmp1 = BN_new();
|
BN_mod(prv->rsa->dmp1, prv->rsa->d, aux, ctx);
|
||||||
BN_mod(prv->dmp1, prv->d, aux, ctx);
|
|
||||||
|
|
||||||
BN_clear_free(aux);
|
BN_clear_free(aux);
|
||||||
BN_CTX_free(ctx);
|
BN_CTX_free(ctx);
|
||||||
|
|
||||||
buffer_free(&decrypted);
|
buffer_free(&decrypted);
|
||||||
|
close(fd);
|
||||||
|
return prv;
|
||||||
|
|
||||||
return 1;
|
fail:
|
||||||
|
if (commentp)
|
||||||
|
xfree(*commentp);
|
||||||
|
close(fd);
|
||||||
|
key_free(prv);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
Key *
|
||||||
load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return)
|
key_load_private_pem(int fd, int type, const char *passphrase,
|
||||||
|
char **commentp)
|
||||||
{
|
{
|
||||||
DSA *dsa;
|
|
||||||
BIO *in;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
EVP_PKEY *pk = NULL;
|
||||||
|
Key *prv = NULL;
|
||||||
|
char *name = "<no key>";
|
||||||
|
|
||||||
in = BIO_new(BIO_s_file());
|
|
||||||
if (in == NULL) {
|
|
||||||
error("BIO_new failed");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
fp = fdopen(fd, "r");
|
fp = fdopen(fd, "r");
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
error("fdopen failed");
|
error("fdopen failed: %s", strerror(errno));
|
||||||
return 0;
|
close(fd);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
BIO_set_fp(in, fp, BIO_NOCLOSE);
|
pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase);
|
||||||
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase);
|
if (pk == NULL) {
|
||||||
if (dsa == NULL) {
|
debug("PEM_read_PrivateKey failed");
|
||||||
debug("PEM_read_bio_DSAPrivateKey failed");
|
(void)ERR_get_error();
|
||||||
} else {
|
} else if (pk->type == EVP_PKEY_RSA &&
|
||||||
/* replace k->dsa with loaded key */
|
(type == KEY_UNSPEC||type==KEY_RSA)) {
|
||||||
DSA_free(k->dsa);
|
prv = key_new(KEY_UNSPEC);
|
||||||
k->dsa = dsa;
|
prv->rsa = EVP_PKEY_get1_RSA(pk);
|
||||||
}
|
prv->type = KEY_RSA;
|
||||||
BIO_free(in);
|
name = "rsa w/o comment";
|
||||||
fclose(fp);
|
#ifdef DEBUG_PK
|
||||||
if (comment_return)
|
RSA_print_fp(stderr, prv->rsa, 8);
|
||||||
*comment_return = xstrdup("dsa w/o comment");
|
|
||||||
debug("read DSA private key done");
|
|
||||||
#ifdef DEBUG_DSS
|
|
||||||
DSA_print_fp(stderr, dsa, 8);
|
|
||||||
#endif
|
#endif
|
||||||
return dsa != NULL ? 1 : 0;
|
} else if (pk->type == EVP_PKEY_DSA &&
|
||||||
|
(type == KEY_UNSPEC||type==KEY_DSA)) {
|
||||||
|
prv = key_new(KEY_UNSPEC);
|
||||||
|
prv->dsa = EVP_PKEY_get1_DSA(pk);
|
||||||
|
prv->type = KEY_DSA;
|
||||||
|
name = "dsa w/o comment";
|
||||||
|
#ifdef DEBUG_PK
|
||||||
|
DSA_print_fp(stderr, prv->dsa, 8);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
error("PEM_read_PrivateKey: mismatch or "
|
||||||
|
"unknown EVP_PKEY save_type %d", pk->save_type);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
if (pk != NULL)
|
||||||
|
EVP_PKEY_free(pk);
|
||||||
|
if (prv != NULL && commentp)
|
||||||
|
*commentp = xstrdup(name);
|
||||||
|
debug("read PEM private key done: type %s",
|
||||||
|
prv ? key_type(prv) : "<unknown>");
|
||||||
|
return prv;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
load_private_key(const char *filename, const char *passphrase, Key *key,
|
key_perm_ok(int fd, const char *filename)
|
||||||
char **comment_return)
|
|
||||||
{
|
{
|
||||||
int fd;
|
|
||||||
int ret = 0;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
||||||
fd = open(filename, O_RDONLY);
|
|
||||||
if (fd < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* check owner and modes */
|
/* check owner and modes */
|
||||||
if (fstat(fd, &st) < 0 ||
|
if (fstat(fd, &st) < 0 ||
|
||||||
(st.st_uid != 0 && st.st_uid != getuid()) ||
|
(st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) ||
|
||||||
(st.st_mode & 077) != 0) {
|
(st.st_mode & 077) != 0) {
|
||||||
close(fd);
|
close(fd);
|
||||||
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
|
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
|
||||||
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
error("Bad ownership or mode(0%3.3o) for '%s'.",
|
error("Bad ownership or mode(0%3.3o) for '%s'.",
|
||||||
st.st_mode & 0777, filename);
|
st.st_mode & 0777, filename);
|
||||||
error("It is recommended that your private key files are NOT accessible by others.");
|
error("It is recommended that your private key files are NOT accessible by others.");
|
||||||
|
error("This private key will be ignored.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
switch (key->type) {
|
return 1;
|
||||||
case KEY_RSA:
|
}
|
||||||
if (key->rsa->e != NULL) {
|
|
||||||
BN_clear_free(key->rsa->e);
|
Key *
|
||||||
key->rsa->e = NULL;
|
key_load_private_type(int type, const char *filename, const char *passphrase,
|
||||||
}
|
char **commentp)
|
||||||
if (key->rsa->n != NULL) {
|
{
|
||||||
BN_clear_free(key->rsa->n);
|
int fd;
|
||||||
key->rsa->n = NULL;
|
|
||||||
}
|
fd = open(filename, O_RDONLY);
|
||||||
ret = load_private_key_rsa(fd, filename, passphrase,
|
if (fd < 0)
|
||||||
key->rsa, comment_return);
|
return NULL;
|
||||||
|
if (!key_perm_ok(fd, filename)) {
|
||||||
|
error("bad permissions: ignore key: %s", filename);
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case KEY_RSA1:
|
||||||
|
return key_load_private_rsa1(fd, filename, passphrase,
|
||||||
|
commentp);
|
||||||
|
/* closes fd */
|
||||||
break;
|
break;
|
||||||
case KEY_DSA:
|
case KEY_DSA:
|
||||||
ret = load_private_key_dsa(fd, passphrase, key, comment_return);
|
case KEY_RSA:
|
||||||
|
case KEY_UNSPEC:
|
||||||
|
return key_load_private_pem(fd, type, passphrase, commentp);
|
||||||
|
/* closes fd */
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
close(fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
close(fd);
|
return NULL;
|
||||||
return ret;
|
}
|
||||||
|
|
||||||
|
Key *
|
||||||
|
key_load_private(const char *filename, const char *passphrase,
|
||||||
|
char **commentp)
|
||||||
|
{
|
||||||
|
Key *pub;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return NULL;
|
||||||
|
if (!key_perm_ok(fd, filename)) {
|
||||||
|
error("bad permissions: ignore key: %s", filename);
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
pub = key_load_public_rsa1(fd, filename, commentp);
|
||||||
|
lseek(fd, (off_t) 0, SEEK_SET); /* rewind */
|
||||||
|
if (pub == NULL) {
|
||||||
|
/* closes fd */
|
||||||
|
return key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL);
|
||||||
|
} else {
|
||||||
|
/* it's a SSH v1 key if the public key part is readable */
|
||||||
|
key_free(pub);
|
||||||
|
/* closes fd */
|
||||||
|
return key_load_private_rsa1(fd, filename, passphrase, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
do_load_public_key(const char *filename, Key *k, char **commentp)
|
key_try_load_public(Key *k, const char *filename, char **commentp)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
unsigned int bits;
|
char line[4096];
|
||||||
char line[1024];
|
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
f = fopen(filename, "r");
|
f = fopen(filename, "r");
|
||||||
@ -538,8 +587,7 @@ do_load_public_key(const char *filename, Key *k, char **commentp)
|
|||||||
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
|
for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
|
||||||
;
|
;
|
||||||
if (*cp) {
|
if (*cp) {
|
||||||
bits = key_read(k, &cp);
|
if (key_read(k, &cp) == 1) {
|
||||||
if (bits != 0) {
|
|
||||||
if (commentp)
|
if (commentp)
|
||||||
*commentp=xstrdup(filename);
|
*commentp=xstrdup(filename);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -552,19 +600,23 @@ do_load_public_key(const char *filename, Key *k, char **commentp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load public key from pubkey file */
|
/* load public key from ssh v1 private or any pubkey file */
|
||||||
int
|
Key *
|
||||||
try_load_public_key(const char *filename, Key *k, char **commentp)
|
key_load_public(const char *filename, char **commentp)
|
||||||
{
|
{
|
||||||
char pub[MAXPATHLEN];
|
Key *pub;
|
||||||
|
char file[MAXPATHLEN];
|
||||||
|
|
||||||
if (do_load_public_key(filename, k, commentp) == 1)
|
pub = key_load_public_type(KEY_RSA1, filename, commentp);
|
||||||
return 1;
|
if (pub != NULL)
|
||||||
if (strlcpy(pub, filename, sizeof pub) >= MAXPATHLEN)
|
return pub;
|
||||||
return 0;
|
pub = key_new(KEY_UNSPEC);
|
||||||
if (strlcat(pub, ".pub", sizeof pub) >= MAXPATHLEN)
|
if (key_try_load_public(pub, filename, commentp) == 1)
|
||||||
return 0;
|
return pub;
|
||||||
if (do_load_public_key(pub, k, commentp) == 1)
|
if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
|
||||||
return 1;
|
(strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
|
||||||
return 0;
|
(key_try_load_public(pub, file, commentp) == 1))
|
||||||
|
return pub;
|
||||||
|
key_free(pub);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -37,14 +37,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: bufaux.c,v 1.13 2000/09/07 20:27:50 deraadt Exp $");
|
RCSID("$OpenBSD: bufaux.c,v 1.17 2001/01/21 19:05:45 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "ssh.h"
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include "bufaux.h"
|
#include "bufaux.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "getput.h"
|
#include "getput.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
|
* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
|
||||||
@ -55,7 +55,7 @@ buffer_put_bignum(Buffer *buffer, BIGNUM *value)
|
|||||||
{
|
{
|
||||||
int bits = BN_num_bits(value);
|
int bits = BN_num_bits(value);
|
||||||
int bin_size = (bits + 7) / 8;
|
int bin_size = (bits + 7) / 8;
|
||||||
char unsigned *buf = xmalloc(bin_size);
|
u_char *buf = xmalloc(bin_size);
|
||||||
int oi;
|
int oi;
|
||||||
char msg[2];
|
char msg[2];
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ int
|
|||||||
buffer_get_bignum(Buffer *buffer, BIGNUM *value)
|
buffer_get_bignum(Buffer *buffer, BIGNUM *value)
|
||||||
{
|
{
|
||||||
int bits, bytes;
|
int bits, bytes;
|
||||||
unsigned char buf[2], *bin;
|
u_char buf[2], *bin;
|
||||||
|
|
||||||
/* Get the number for bits. */
|
/* Get the number for bits. */
|
||||||
buffer_get(buffer, (char *) buf, 2);
|
buffer_get(buffer, (char *) buf, 2);
|
||||||
@ -91,7 +91,7 @@ buffer_get_bignum(Buffer *buffer, BIGNUM *value)
|
|||||||
bytes = (bits + 7) / 8;
|
bytes = (bits + 7) / 8;
|
||||||
if (buffer_len(buffer) < bytes)
|
if (buffer_len(buffer) < bytes)
|
||||||
fatal("buffer_get_bignum: input buffer too small");
|
fatal("buffer_get_bignum: input buffer too small");
|
||||||
bin = (unsigned char*) buffer_ptr(buffer);
|
bin = (u_char *) buffer_ptr(buffer);
|
||||||
BN_bin2bn(bin, bytes, value);
|
BN_bin2bn(bin, bytes, value);
|
||||||
buffer_consume(buffer, bytes);
|
buffer_consume(buffer, bytes);
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ void
|
|||||||
buffer_put_bignum2(Buffer *buffer, BIGNUM *value)
|
buffer_put_bignum2(Buffer *buffer, BIGNUM *value)
|
||||||
{
|
{
|
||||||
int bytes = BN_num_bytes(value) + 1;
|
int bytes = BN_num_bytes(value) + 1;
|
||||||
unsigned char *buf = xmalloc(bytes);
|
u_char *buf = xmalloc(bytes);
|
||||||
int oi;
|
int oi;
|
||||||
int hasnohigh = 0;
|
int hasnohigh = 0;
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
@ -118,7 +118,7 @@ buffer_put_bignum2(Buffer *buffer, BIGNUM *value)
|
|||||||
if (value->neg) {
|
if (value->neg) {
|
||||||
/**XXX should be two's-complement */
|
/**XXX should be two's-complement */
|
||||||
int i, carry;
|
int i, carry;
|
||||||
unsigned char *uc = buf;
|
u_char *uc = buf;
|
||||||
log("negativ!");
|
log("negativ!");
|
||||||
for(i = bytes-1, carry = 1; i>=0; i--) {
|
for(i = bytes-1, carry = 1; i>=0; i--) {
|
||||||
uc[i] ^= 0xff;
|
uc[i] ^= 0xff;
|
||||||
@ -136,7 +136,7 @@ buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
|
|||||||
{
|
{
|
||||||
/**XXX should be two's-complement */
|
/**XXX should be two's-complement */
|
||||||
int len;
|
int len;
|
||||||
unsigned char *bin = (unsigned char *)buffer_get_string(buffer, (unsigned int *)&len);
|
u_char *bin = (u_char *)buffer_get_string(buffer, (u_int *)&len);
|
||||||
BN_bin2bn(bin, len, value);
|
BN_bin2bn(bin, len, value);
|
||||||
xfree(bin);
|
xfree(bin);
|
||||||
return len;
|
return len;
|
||||||
@ -145,25 +145,41 @@ buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
|
|||||||
/*
|
/*
|
||||||
* Returns an integer from the buffer (4 bytes, msb first).
|
* Returns an integer from the buffer (4 bytes, msb first).
|
||||||
*/
|
*/
|
||||||
unsigned int
|
u_int
|
||||||
buffer_get_int(Buffer *buffer)
|
buffer_get_int(Buffer *buffer)
|
||||||
{
|
{
|
||||||
unsigned char buf[4];
|
u_char buf[4];
|
||||||
buffer_get(buffer, (char *) buf, 4);
|
buffer_get(buffer, (char *) buf, 4);
|
||||||
return GET_32BIT(buf);
|
return GET_32BIT(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u_int64_t
|
||||||
|
buffer_get_int64(Buffer *buffer)
|
||||||
|
{
|
||||||
|
u_char buf[8];
|
||||||
|
buffer_get(buffer, (char *) buf, 8);
|
||||||
|
return GET_64BIT(buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stores an integer in the buffer in 4 bytes, msb first.
|
* Stores an integer in the buffer in 4 bytes, msb first.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
buffer_put_int(Buffer *buffer, unsigned int value)
|
buffer_put_int(Buffer *buffer, u_int value)
|
||||||
{
|
{
|
||||||
char buf[4];
|
char buf[4];
|
||||||
PUT_32BIT(buf, value);
|
PUT_32BIT(buf, value);
|
||||||
buffer_append(buffer, buf, 4);
|
buffer_append(buffer, buf, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
buffer_put_int64(Buffer *buffer, u_int64_t value)
|
||||||
|
{
|
||||||
|
char buf[8];
|
||||||
|
PUT_64BIT(buf, value);
|
||||||
|
buffer_append(buffer, buf, 8);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns an arbitrary binary string from the buffer. The string cannot
|
* Returns an arbitrary binary string from the buffer. The string cannot
|
||||||
* be longer than 256k. The returned value points to memory allocated
|
* be longer than 256k. The returned value points to memory allocated
|
||||||
@ -173,9 +189,9 @@ buffer_put_int(Buffer *buffer, unsigned int value)
|
|||||||
* to the returned string, and is not counted in length.
|
* to the returned string, and is not counted in length.
|
||||||
*/
|
*/
|
||||||
char *
|
char *
|
||||||
buffer_get_string(Buffer *buffer, unsigned int *length_ptr)
|
buffer_get_string(Buffer *buffer, u_int *length_ptr)
|
||||||
{
|
{
|
||||||
unsigned int len;
|
u_int len;
|
||||||
char *value;
|
char *value;
|
||||||
/* Get the length. */
|
/* Get the length. */
|
||||||
len = buffer_get_int(buffer);
|
len = buffer_get_int(buffer);
|
||||||
@ -197,7 +213,7 @@ buffer_get_string(Buffer *buffer, unsigned int *length_ptr)
|
|||||||
* Stores and arbitrary binary string in the buffer.
|
* Stores and arbitrary binary string in the buffer.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
buffer_put_string(Buffer *buffer, const void *buf, unsigned int len)
|
buffer_put_string(Buffer *buffer, const void *buf, u_int len)
|
||||||
{
|
{
|
||||||
buffer_put_int(buffer, len);
|
buffer_put_int(buffer, len);
|
||||||
buffer_append(buffer, buf, len);
|
buffer_append(buffer, buf, len);
|
||||||
@ -216,7 +232,7 @@ buffer_get_char(Buffer *buffer)
|
|||||||
{
|
{
|
||||||
char ch;
|
char ch;
|
||||||
buffer_get(buffer, &ch, 1);
|
buffer_get(buffer, &ch, 1);
|
||||||
return (unsigned char) ch;
|
return (u_char) ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -12,12 +12,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: canohost.c,v 1.16 2000/10/21 17:04:22 markus Exp $");
|
RCSID("$OpenBSD: canohost.c,v 1.26 2001/04/18 14:15:00 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
#include "log.h"
|
||||||
|
#include "canohost.h"
|
||||||
|
|
||||||
|
void check_ip_options(int socket, char *ipaddr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the canonical name of the host at the other end of the socket. The
|
* Return the canonical name of the host at the other end of the socket. The
|
||||||
@ -25,121 +28,124 @@ RCSID("$FreeBSD$");
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
get_remote_hostname(int socket)
|
get_remote_hostname(int socket, int reverse_mapping_check)
|
||||||
{
|
{
|
||||||
struct sockaddr_storage from;
|
struct sockaddr_storage from;
|
||||||
int i;
|
int i;
|
||||||
socklen_t fromlen;
|
socklen_t fromlen;
|
||||||
struct addrinfo hints, *ai, *aitop;
|
struct addrinfo hints, *ai, *aitop;
|
||||||
char name[MAXHOSTNAMELEN];
|
char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
|
||||||
char ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
|
|
||||||
|
|
||||||
/* Get IP address of client. */
|
/* Get IP address of client. */
|
||||||
fromlen = sizeof(from);
|
fromlen = sizeof(from);
|
||||||
memset(&from, 0, sizeof(from));
|
memset(&from, 0, sizeof(from));
|
||||||
if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
|
if (getpeername(socket, (struct sockaddr *) &from, &fromlen) < 0) {
|
||||||
debug("getpeername failed: %.100s", strerror(errno));
|
debug("getpeername failed: %.100s", strerror(errno));
|
||||||
fatal_cleanup();
|
fatal_cleanup();
|
||||||
}
|
}
|
||||||
|
if (from.ss_family == AF_INET)
|
||||||
|
check_ip_options(socket, ntop);
|
||||||
|
|
||||||
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
|
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
|
||||||
NULL, 0, NI_NUMERICHOST) != 0)
|
NULL, 0, NI_NUMERICHOST) != 0)
|
||||||
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
|
fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
|
||||||
|
|
||||||
|
debug3("Trying to reverse map address %.100s.", ntop);
|
||||||
/* Map the IP address to a host name. */
|
/* Map the IP address to a host name. */
|
||||||
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
|
if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
|
||||||
NULL, 0, NI_NAMEREQD) == 0) {
|
NULL, 0, NI_NAMEREQD) != 0) {
|
||||||
/* Got host name. */
|
/* Host name not found. Use ip address. */
|
||||||
name[sizeof(name) - 1] = '\0';
|
log("Could not reverse map address %.100s.", ntop);
|
||||||
/*
|
return xstrdup(ntop);
|
||||||
* Convert it to all lowercase (which is expected by the rest
|
|
||||||
* of this software).
|
|
||||||
*/
|
|
||||||
for (i = 0; name[i]; i++)
|
|
||||||
if (isupper(name[i]))
|
|
||||||
name[i] = tolower(name[i]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Map it back to an IP address and check that the given
|
|
||||||
* address actually is an address of this host. This is
|
|
||||||
* necessary because anyone with access to a name server can
|
|
||||||
* define arbitrary names for an IP address. Mapping from
|
|
||||||
* name to IP address can be trusted better (but can still be
|
|
||||||
* fooled if the intruder has access to the name server of
|
|
||||||
* the domain).
|
|
||||||
*/
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
|
||||||
hints.ai_family = from.ss_family;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
|
|
||||||
log("reverse mapping checking getaddrinfo for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
|
|
||||||
strlcpy(name, ntop, sizeof name);
|
|
||||||
goto check_ip_options;
|
|
||||||
}
|
|
||||||
/* Look for the address from the list of addresses. */
|
|
||||||
for (ai = aitop; ai; ai = ai->ai_next) {
|
|
||||||
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
|
|
||||||
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
|
|
||||||
(strcmp(ntop, ntop2) == 0))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
freeaddrinfo(aitop);
|
|
||||||
/* If we reached the end of the list, the address was not there. */
|
|
||||||
if (!ai) {
|
|
||||||
/* Address not found for the host name. */
|
|
||||||
log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
|
|
||||||
ntop, name);
|
|
||||||
strlcpy(name, ntop, sizeof name);
|
|
||||||
goto check_ip_options;
|
|
||||||
}
|
|
||||||
/* Address was found for the host name. We accept the host name. */
|
|
||||||
} else {
|
|
||||||
/* Host name not found. Use ascii representation of the address. */
|
|
||||||
strlcpy(name, ntop, sizeof name);
|
|
||||||
log("Could not reverse map address %.100s.", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
check_ip_options:
|
/* Got host name. */
|
||||||
|
name[sizeof(name) - 1] = '\0';
|
||||||
/*
|
/*
|
||||||
* If IP options are supported, make sure there are none (log and
|
* Convert it to all lowercase (which is expected by the rest
|
||||||
* disconnect them if any are found). Basically we are worried about
|
* of this software).
|
||||||
* source routing; it can be used to pretend you are somebody
|
|
||||||
* (ip-address) you are not. That itself may be "almost acceptable"
|
|
||||||
* under certain circumstances, but rhosts autentication is useless
|
|
||||||
* if source routing is accepted. Notice also that if we just dropped
|
|
||||||
* source routing here, the other side could use IP spoofing to do
|
|
||||||
* rest of the interaction and could still bypass security. So we
|
|
||||||
* exit here if we detect any IP options.
|
|
||||||
*/
|
*/
|
||||||
/* IP options -- IPv4 only */
|
for (i = 0; name[i]; i++)
|
||||||
if (from.ss_family == AF_INET) {
|
if (isupper(name[i]))
|
||||||
unsigned char options[200], *ucp;
|
name[i] = tolower(name[i]);
|
||||||
char text[1024], *cp;
|
|
||||||
socklen_t option_size;
|
|
||||||
int ipproto;
|
|
||||||
struct protoent *ip;
|
|
||||||
|
|
||||||
if ((ip = getprotobyname("ip")) != NULL)
|
if (!reverse_mapping_check)
|
||||||
ipproto = ip->p_proto;
|
return xstrdup(name);
|
||||||
else
|
/*
|
||||||
ipproto = IPPROTO_IP;
|
* Map it back to an IP address and check that the given
|
||||||
option_size = sizeof(options);
|
* address actually is an address of this host. This is
|
||||||
if (getsockopt(socket, ipproto, IP_OPTIONS, (char *) options,
|
* necessary because anyone with access to a name server can
|
||||||
&option_size) >= 0 && option_size != 0) {
|
* define arbitrary names for an IP address. Mapping from
|
||||||
cp = text;
|
* name to IP address can be trusted better (but can still be
|
||||||
/* Note: "text" buffer must be at least 3x as big as options. */
|
* fooled if the intruder has access to the name server of
|
||||||
for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
|
* the domain).
|
||||||
sprintf(cp, " %2.2x", *ucp);
|
*/
|
||||||
log("Connection from %.100s with IP options:%.800s",
|
memset(&hints, 0, sizeof(hints));
|
||||||
ntop, text);
|
hints.ai_family = from.ss_family;
|
||||||
packet_disconnect("Connection from %.100s with IP options:%.800s",
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
ntop, text);
|
if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
|
||||||
}
|
log("reverse mapping checking getaddrinfo for %.700s "
|
||||||
|
"failed - POSSIBLE BREAKIN ATTEMPT!", name);
|
||||||
|
return xstrdup(ntop);
|
||||||
|
}
|
||||||
|
/* Look for the address from the list of addresses. */
|
||||||
|
for (ai = aitop; ai; ai = ai->ai_next) {
|
||||||
|
if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
|
||||||
|
sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
|
||||||
|
(strcmp(ntop, ntop2) == 0))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
freeaddrinfo(aitop);
|
||||||
|
/* If we reached the end of the list, the address was not there. */
|
||||||
|
if (!ai) {
|
||||||
|
/* Address not found for the host name. */
|
||||||
|
log("Address %.100s maps to %.600s, but this does not "
|
||||||
|
"map back to the address - POSSIBLE BREAKIN ATTEMPT!",
|
||||||
|
ntop, name);
|
||||||
|
return xstrdup(ntop);
|
||||||
}
|
}
|
||||||
|
|
||||||
return xstrdup(name);
|
return xstrdup(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If IP options are supported, make sure there are none (log and
|
||||||
|
* disconnect them if any are found). Basically we are worried about
|
||||||
|
* source routing; it can be used to pretend you are somebody
|
||||||
|
* (ip-address) you are not. That itself may be "almost acceptable"
|
||||||
|
* under certain circumstances, but rhosts autentication is useless
|
||||||
|
* if source routing is accepted. Notice also that if we just dropped
|
||||||
|
* source routing here, the other side could use IP spoofing to do
|
||||||
|
* rest of the interaction and could still bypass security. So we
|
||||||
|
* exit here if we detect any IP options.
|
||||||
|
*/
|
||||||
|
/* IPv4 only */
|
||||||
|
void
|
||||||
|
check_ip_options(int socket, char *ipaddr)
|
||||||
|
{
|
||||||
|
u_char options[200];
|
||||||
|
char text[sizeof(options) * 3 + 1];
|
||||||
|
socklen_t option_size;
|
||||||
|
int i, ipproto;
|
||||||
|
struct protoent *ip;
|
||||||
|
|
||||||
|
if ((ip = getprotobyname("ip")) != NULL)
|
||||||
|
ipproto = ip->p_proto;
|
||||||
|
else
|
||||||
|
ipproto = IPPROTO_IP;
|
||||||
|
option_size = sizeof(options);
|
||||||
|
if (getsockopt(socket, ipproto, IP_OPTIONS, (void *)options,
|
||||||
|
&option_size) >= 0 && option_size != 0) {
|
||||||
|
text[0] = '\0';
|
||||||
|
for (i = 0; i < option_size; i++)
|
||||||
|
snprintf(text + i*3, sizeof(text) - i*3,
|
||||||
|
" %2.2x", options[i]);
|
||||||
|
log("Connection from %.100s with IP options:%.800s",
|
||||||
|
ipaddr, text);
|
||||||
|
packet_disconnect("Connection from %.100s with IP options:%.800s",
|
||||||
|
ipaddr, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return the canonical name of the host in the other side of the current
|
* Return the canonical name of the host in the other side of the current
|
||||||
* connection. The host name is cached, so it is efficient to call this
|
* connection. The host name is cached, so it is efficient to call this
|
||||||
@ -147,23 +153,87 @@ get_remote_hostname(int socket)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
get_canonical_hostname()
|
get_canonical_hostname(int reverse_mapping_check)
|
||||||
{
|
{
|
||||||
static char *canonical_host_name = NULL;
|
static char *canonical_host_name = NULL;
|
||||||
|
static int reverse_mapping_checked = 0;
|
||||||
|
|
||||||
/* Check if we have previously retrieved this same name. */
|
/* Check if we have previously retrieved name with same option. */
|
||||||
if (canonical_host_name != NULL)
|
if (canonical_host_name != NULL) {
|
||||||
return canonical_host_name;
|
if (reverse_mapping_checked != reverse_mapping_check)
|
||||||
|
xfree(canonical_host_name);
|
||||||
|
else
|
||||||
|
return canonical_host_name;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the real hostname if socket; otherwise return UNKNOWN. */
|
/* Get the real hostname if socket; otherwise return UNKNOWN. */
|
||||||
if (packet_connection_is_on_socket())
|
if (packet_connection_is_on_socket())
|
||||||
canonical_host_name = get_remote_hostname(packet_get_connection_in());
|
canonical_host_name = get_remote_hostname(
|
||||||
|
packet_get_connection_in(), reverse_mapping_check);
|
||||||
else
|
else
|
||||||
canonical_host_name = xstrdup("UNKNOWN");
|
canonical_host_name = xstrdup("UNKNOWN");
|
||||||
|
|
||||||
|
reverse_mapping_checked = reverse_mapping_check;
|
||||||
return canonical_host_name;
|
return canonical_host_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the remote IP-address of socket as a string. The returned
|
||||||
|
* string must be freed.
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
get_socket_address(int socket, int remote, int flags)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t addrlen;
|
||||||
|
char ntop[NI_MAXHOST];
|
||||||
|
|
||||||
|
/* Get IP address of client. */
|
||||||
|
addrlen = sizeof(addr);
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
|
||||||
|
if (remote) {
|
||||||
|
if (getpeername(socket, (struct sockaddr *)&addr, &addrlen)
|
||||||
|
< 0) {
|
||||||
|
debug("get_socket_ipaddr: getpeername failed: %.100s",
|
||||||
|
strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (getsockname(socket, (struct sockaddr *)&addr, &addrlen)
|
||||||
|
< 0) {
|
||||||
|
debug("get_socket_ipaddr: getsockname failed: %.100s",
|
||||||
|
strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Get the address in ascii. */
|
||||||
|
if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop),
|
||||||
|
NULL, 0, flags) != 0) {
|
||||||
|
error("get_socket_ipaddr: getnameinfo %d failed", flags);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return xstrdup(ntop);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
get_peer_ipaddr(int socket)
|
||||||
|
{
|
||||||
|
return get_socket_address(socket, 1, NI_NUMERICHOST);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
get_local_ipaddr(int socket)
|
||||||
|
{
|
||||||
|
return get_socket_address(socket, 0, NI_NUMERICHOST);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
get_local_name(int socket)
|
||||||
|
{
|
||||||
|
return get_socket_address(socket, 0, NI_NAMEREQD);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the IP-address of the remote host as a string. The returned
|
* Returns the IP-address of the remote host as a string. The returned
|
||||||
* string must not be freed.
|
* string must not be freed.
|
||||||
@ -173,68 +243,31 @@ const char *
|
|||||||
get_remote_ipaddr()
|
get_remote_ipaddr()
|
||||||
{
|
{
|
||||||
static char *canonical_host_ip = NULL;
|
static char *canonical_host_ip = NULL;
|
||||||
struct sockaddr_storage from;
|
|
||||||
socklen_t fromlen;
|
|
||||||
int socket;
|
|
||||||
char ntop[NI_MAXHOST];
|
|
||||||
|
|
||||||
/* Check whether we have chached the name. */
|
/* Check whether we have cached the ipaddr. */
|
||||||
if (canonical_host_ip != NULL)
|
if (canonical_host_ip == NULL) {
|
||||||
return canonical_host_ip;
|
if (packet_connection_is_on_socket()) {
|
||||||
|
canonical_host_ip =
|
||||||
/* If not a socket, return UNKNOWN. */
|
get_peer_ipaddr(packet_get_connection_in());
|
||||||
if (!packet_connection_is_on_socket()) {
|
if (canonical_host_ip == NULL)
|
||||||
canonical_host_ip = xstrdup("UNKNOWN");
|
fatal_cleanup();
|
||||||
return canonical_host_ip;
|
} else {
|
||||||
|
/* If not on socket, return UNKNOWN. */
|
||||||
|
canonical_host_ip = xstrdup("UNKNOWN");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Get client socket. */
|
|
||||||
socket = packet_get_connection_in();
|
|
||||||
|
|
||||||
/* Get IP address of client. */
|
|
||||||
fromlen = sizeof(from);
|
|
||||||
memset(&from, 0, sizeof(from));
|
|
||||||
if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {
|
|
||||||
debug("getpeername failed: %.100s", strerror(errno));
|
|
||||||
fatal_cleanup();
|
|
||||||
}
|
|
||||||
/* Get the IP address in ascii. */
|
|
||||||
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
|
|
||||||
NULL, 0, NI_NUMERICHOST) != 0)
|
|
||||||
fatal("get_remote_ipaddr: getnameinfo NI_NUMERICHOST failed");
|
|
||||||
|
|
||||||
canonical_host_ip = xstrdup(ntop);
|
|
||||||
|
|
||||||
/* Return ip address string. */
|
|
||||||
return canonical_host_ip;
|
return canonical_host_ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the IP-address of the local host as a string. The returned
|
|
||||||
* string must be freed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
get_ipaddr(int socket)
|
get_remote_name_or_ip(u_int utmp_len, int reverse_mapping_check)
|
||||||
{
|
{
|
||||||
static char *canonical_host_ip = NULL;
|
static const char *remote = "";
|
||||||
struct sockaddr_storage from;
|
if (utmp_len > 0)
|
||||||
socklen_t fromlen;
|
remote = get_canonical_hostname(reverse_mapping_check);
|
||||||
char ntop[NI_MAXHOST];
|
if (utmp_len == 0 || strlen(remote) > utmp_len)
|
||||||
|
remote = get_remote_ipaddr();
|
||||||
/* Get IP address of server. */
|
return remote;
|
||||||
fromlen = sizeof(from);
|
|
||||||
memset(&from, 0, sizeof(from));
|
|
||||||
if (getsockname(socket, (struct sockaddr *)&from, &fromlen) < 0) {
|
|
||||||
debug("getsockname failed: %.100s", strerror(errno));
|
|
||||||
fatal_cleanup();
|
|
||||||
}
|
|
||||||
/* Get the IP address in ascii. */
|
|
||||||
if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
|
|
||||||
NULL, 0, NI_NUMERICHOST) != 0)
|
|
||||||
fatal("get_local_ipaddr: getnameinfo NI_NUMERICHOST failed");
|
|
||||||
|
|
||||||
/* Return ip address string. */
|
|
||||||
return xstrdup(ntop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the local/remote port for the socket. */
|
/* Returns the local/remote port for the socket. */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -32,12 +32,14 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
/* RCSID("$OpenBSD: channels.h,v 1.31 2001/04/13 22:46:53 beck Exp $"); */
|
||||||
/* RCSID("$FreeBSD$"); */
|
/* RCSID("$FreeBSD$"); */
|
||||||
/* RCSID("$OpenBSD: channels.h,v 1.22 2000/10/27 07:48:22 markus Exp $"); */
|
|
||||||
|
|
||||||
#ifndef CHANNELS_H
|
#ifndef CHANNELS_H
|
||||||
#define CHANNELS_H
|
#define CHANNELS_H
|
||||||
|
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
/* Definitions for channel types. */
|
/* Definitions for channel types. */
|
||||||
#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
|
#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
|
||||||
#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
|
#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
|
||||||
@ -50,7 +52,10 @@
|
|||||||
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
|
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
|
||||||
#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
|
#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
|
||||||
#define SSH_CHANNEL_LARVAL 10 /* larval session */
|
#define SSH_CHANNEL_LARVAL 10 /* larval session */
|
||||||
#define SSH_CHANNEL_MAX_TYPE 11
|
#define SSH_CHANNEL_RPORT_LISTENER 11 /* Listening to a R-style port */
|
||||||
|
#define SSH_CHANNEL_CONNECTING 12
|
||||||
|
#define SSH_CHANNEL_DYNAMIC 13
|
||||||
|
#define SSH_CHANNEL_MAX_TYPE 14
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data structure for channel data. This is iniailized in channel_allocate
|
* Data structure for channel data. This is iniailized in channel_allocate
|
||||||
@ -149,7 +154,6 @@ void channel_input_open_confirmation(int type, int plen, void *ctxt);
|
|||||||
void channel_input_open_failure(int type, int plen, void *ctxt);
|
void channel_input_open_failure(int type, int plen, void *ctxt);
|
||||||
void channel_input_port_open(int type, int plen, void *ctxt);
|
void channel_input_port_open(int type, int plen, void *ctxt);
|
||||||
void channel_input_window_adjust(int type, int plen, void *ctxt);
|
void channel_input_window_adjust(int type, int plen, void *ctxt);
|
||||||
void channel_input_open(int type, int plen, void *ctxt);
|
|
||||||
|
|
||||||
/* Sets specific protocol options. */
|
/* Sets specific protocol options. */
|
||||||
void channel_set_options(int hostname_in_open);
|
void channel_set_options(int hostname_in_open);
|
||||||
@ -164,8 +168,13 @@ int channel_allocate(int type, int sock, char *remote_name);
|
|||||||
/* Free the channel and close its socket. */
|
/* Free the channel and close its socket. */
|
||||||
void channel_free(int channel);
|
void channel_free(int channel);
|
||||||
|
|
||||||
/* Add any bits relevant to channels in select bitmasks. */
|
/*
|
||||||
void channel_prepare_select(fd_set * readset, fd_set * writeset);
|
* Allocate/update select bitmasks and add any bits relevant to channels in
|
||||||
|
* select bitmasks.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
channel_prepare_select(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
|
||||||
|
int rekeying);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* After select, perform any appropriate operations for channels which have
|
* After select, perform any appropriate operations for channels which have
|
||||||
@ -189,9 +198,6 @@ void channel_stop_listening(void);
|
|||||||
*/
|
*/
|
||||||
void channel_close_all(void);
|
void channel_close_all(void);
|
||||||
|
|
||||||
/* Returns the maximum file descriptor number used by the channels. */
|
|
||||||
int channel_max_fd(void);
|
|
||||||
|
|
||||||
/* Returns true if there is still an open channel over the connection. */
|
/* Returns true if there is still an open channel over the connection. */
|
||||||
int channel_still_open(void);
|
int channel_still_open(void);
|
||||||
|
|
||||||
@ -204,12 +210,15 @@ char *channel_open_message(void);
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Initiate forwarding of connections to local port "port" through the secure
|
* Initiate forwarding of connections to local port "port" through the secure
|
||||||
* channel to host:port from remote side. This never returns if there was an
|
* channel to host:port from remote side.
|
||||||
* error.
|
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
channel_request_local_forwarding(u_short port, const char *host,
|
channel_request_local_forwarding(u_short listen_port,
|
||||||
u_short remote_port, int gateway_ports);
|
const char *host_to_connect, u_short port_to_connect, int gateway_ports);
|
||||||
|
int
|
||||||
|
channel_request_forwarding(const char *listen_address, u_short listen_port,
|
||||||
|
const char *host_to_connect, u_short port_to_connect, int gateway_ports,
|
||||||
|
int remote_fwd);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initiate forwarding of connections to port "port" on remote host through
|
* Initiate forwarding of connections to port "port" on remote host through
|
||||||
@ -222,12 +231,18 @@ channel_request_remote_forwarding(u_short port, const char *host,
|
|||||||
u_short remote_port);
|
u_short remote_port);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
|
* Permits opening to any host/port if permitted_opens[] is empty. This is
|
||||||
* called by the server, because the user could connect to any port anyway,
|
* usually called by the server, because the user could connect to any port
|
||||||
* and the server has no way to know but to trust the client anyway.
|
* anyway, and the server has no way to know but to trust the client anyway.
|
||||||
*/
|
*/
|
||||||
void channel_permit_all_opens(void);
|
void channel_permit_all_opens(void);
|
||||||
|
|
||||||
|
/* Add host/port to list of allowed targets for port forwarding */
|
||||||
|
void channel_add_permitted_opens(char *host, int port);
|
||||||
|
|
||||||
|
/* Flush list */
|
||||||
|
void channel_clear_permitted_opens(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
|
* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
|
||||||
* listening for the port, and sends back a success reply (or disconnect
|
* listening for the port, and sends back a success reply (or disconnect
|
||||||
@ -290,6 +305,9 @@ void auth_input_open_request(int type, int plen, void *ctxt);
|
|||||||
|
|
||||||
/* XXX */
|
/* XXX */
|
||||||
int channel_connect_to(const char *host, u_short host_port);
|
int channel_connect_to(const char *host, u_short host_port);
|
||||||
|
int channel_connect_by_listen_adress(u_short listen_port);
|
||||||
int x11_connect_display(void);
|
int x11_connect_display(void);
|
||||||
|
|
||||||
|
int channel_find_open(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,11 +35,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: cipher.c,v 1.37 2000/10/23 19:31:54 markus Exp $");
|
RCSID("$OpenBSD: cipher.c,v 1.43 2001/02/04 15:32:23 stevesk Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "ssh.h"
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "cipher.h"
|
||||||
|
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
|
|
||||||
@ -155,14 +156,9 @@ des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
|||||||
|
|
||||||
memcpy(&iv1, iv2, 8);
|
memcpy(&iv1, iv2, 8);
|
||||||
|
|
||||||
des_cbc_encrypt(src, dest, len, cc->u.des3.key1, &iv1, DES_ENCRYPT);
|
des_ncbc_encrypt(src, dest, len, cc->u.des3.key1, &iv1, DES_ENCRYPT);
|
||||||
memcpy(&iv1, dest + len - 8, 8);
|
des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_DECRYPT);
|
||||||
|
des_ncbc_encrypt(dest, dest, len, cc->u.des3.key3, iv3, DES_ENCRYPT);
|
||||||
des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_DECRYPT);
|
|
||||||
memcpy(iv2, &iv1, 8); /* Note how iv1 == iv2 on entry and exit. */
|
|
||||||
|
|
||||||
des_cbc_encrypt(dest, dest, len, cc->u.des3.key3, iv3, DES_ENCRYPT);
|
|
||||||
memcpy(iv3, dest + len - 8, 8);
|
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
||||||
@ -174,22 +170,16 @@ des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
|||||||
|
|
||||||
memcpy(&iv1, iv2, 8);
|
memcpy(&iv1, iv2, 8);
|
||||||
|
|
||||||
des_cbc_encrypt(src, dest, len, cc->u.des3.key3, iv3, DES_DECRYPT);
|
des_ncbc_encrypt(src, dest, len, cc->u.des3.key3, iv3, DES_DECRYPT);
|
||||||
memcpy(iv3, src + len - 8, 8);
|
des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_ENCRYPT);
|
||||||
|
des_ncbc_encrypt(dest, dest, len, cc->u.des3.key1, &iv1, DES_DECRYPT);
|
||||||
des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_ENCRYPT);
|
|
||||||
memcpy(iv2, dest + len - 8, 8);
|
|
||||||
|
|
||||||
des_cbc_encrypt(dest, dest, len, cc->u.des3.key1, &iv1, DES_DECRYPT);
|
|
||||||
/* memcpy(&iv1, iv2, 8); */
|
|
||||||
/* Note how iv1 == iv2 on entry and exit. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Blowfish */
|
/* Blowfish */
|
||||||
void
|
void
|
||||||
blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||||
{
|
{
|
||||||
BF_set_key(&cc->u.bf.key, keylen, (unsigned char *)key);
|
BF_set_key(&cc->u.bf.key, keylen, (u_char *)key);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||||
@ -219,7 +209,7 @@ blowfish_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
|
|||||||
* and after encryption/decryption. Thus the swap_bytes stuff (yuk).
|
* and after encryption/decryption. Thus the swap_bytes stuff (yuk).
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
swap_bytes(const unsigned char *src, unsigned char *dst, int n)
|
swap_bytes(const u_char *src, u_char *dst, int n)
|
||||||
{
|
{
|
||||||
char c[4];
|
char c[4];
|
||||||
|
|
||||||
@ -272,12 +262,12 @@ arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
|
|||||||
void
|
void
|
||||||
cast_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
cast_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
||||||
{
|
{
|
||||||
CAST_set_key(&cc->u.cast.key, keylen, (unsigned char *) key);
|
CAST_set_key(&cc->u.cast.key, keylen, (u_char *) key);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||||
{
|
{
|
||||||
if (iv == NULL)
|
if (iv == NULL)
|
||||||
fatal("no IV for %s.", cc->cipher->name);
|
fatal("no IV for %s.", cc->cipher->name);
|
||||||
memcpy(cc->u.cast.iv, (char *)iv, 8);
|
memcpy(cc->u.cast.iv, (char *)iv, 8);
|
||||||
}
|
}
|
||||||
@ -306,7 +296,7 @@ rijndael_setkey(CipherContext *cc, const u_char *key, u_int keylen)
|
|||||||
void
|
void
|
||||||
rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
|
||||||
{
|
{
|
||||||
if (iv == NULL)
|
if (iv == NULL)
|
||||||
fatal("no IV for %s.", cc->cipher->name);
|
fatal("no IV for %s.", cc->cipher->name);
|
||||||
memcpy((u_char *)cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE);
|
memcpy((u_char *)cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE);
|
||||||
}
|
}
|
||||||
@ -426,15 +416,15 @@ Cipher ciphers[] = {
|
|||||||
SSH_CIPHER_SSH2, 16, 32,
|
SSH_CIPHER_SSH2, 16, 32,
|
||||||
rijndael_setkey, rijndael_setiv,
|
rijndael_setkey, rijndael_setiv,
|
||||||
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
rijndael_cbc_encrypt, rijndael_cbc_decrypt },
|
||||||
{ NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL }
|
{ NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
unsigned int
|
u_int
|
||||||
cipher_mask_ssh1(int client)
|
cipher_mask_ssh1(int client)
|
||||||
{
|
{
|
||||||
unsigned int mask = 0;
|
u_int mask = 0;
|
||||||
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
|
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
|
||||||
mask |= 1 << SSH_CIPHER_BLOWFISH;
|
mask |= 1 << SSH_CIPHER_BLOWFISH;
|
||||||
if (client) {
|
if (client) {
|
||||||
@ -553,7 +543,7 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher,
|
|||||||
const char *passphrase)
|
const char *passphrase)
|
||||||
{
|
{
|
||||||
MD5_CTX md;
|
MD5_CTX md;
|
||||||
unsigned char digest[16];
|
u_char digest[16];
|
||||||
|
|
||||||
MD5_Init(&md);
|
MD5_Init(&md);
|
||||||
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
|
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));
|
||||||
|
@ -32,8 +32,8 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: cipher.h,v 1.22 2000/10/13 18:59:14 markus Exp $"); */
|
/* RCSID("$OpenBSD: cipher.h,v 1.25 2000/12/19 23:17:56 markus Exp $"); */
|
||||||
/* $FreeBSD$ */
|
/* RCSID("$FreeBSD$"); */
|
||||||
|
|
||||||
#ifndef CIPHER_H
|
#ifndef CIPHER_H
|
||||||
#define CIPHER_H
|
#define CIPHER_H
|
||||||
@ -104,7 +104,7 @@ struct Cipher {
|
|||||||
void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int);
|
void (*decrypt)(CipherContext *, u_char *, const u_char *, u_int);
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned int cipher_mask_ssh1(int client);
|
u_int cipher_mask_ssh1(int client);
|
||||||
Cipher *cipher_by_name(const char *name);
|
Cipher *cipher_by_name(const char *name);
|
||||||
Cipher *cipher_by_number(int id);
|
Cipher *cipher_by_number(int id);
|
||||||
int cipher_number(const char *name);
|
int cipher_number(const char *name);
|
||||||
|
@ -24,13 +24,14 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
RCSID("$OpenBSD: compat.c,v 1.27 2000/10/31 09:31:58 markus Exp $");
|
RCSID("$OpenBSD: compat.c,v 1.47 2001/04/18 23:43:25 markus Exp $");
|
||||||
|
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
#include "ssh.h"
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include <regex.h>
|
#include "log.h"
|
||||||
|
|
||||||
int compat13 = 0;
|
int compat13 = 0;
|
||||||
int compat20 = 0;
|
int compat20 = 0;
|
||||||
@ -59,22 +60,55 @@ compat_datafellows(const char *version)
|
|||||||
char *pat;
|
char *pat;
|
||||||
int bugs;
|
int bugs;
|
||||||
} check[] = {
|
} check[] = {
|
||||||
{ "^OpenSSH[-_]2\\.3", 0 },
|
{ "^OpenSSH[-_]2\\.[012]",
|
||||||
{ "^OpenSSH[-_]2\\.[012]", SSH_OLD_SESSIONID },
|
SSH_OLD_SESSIONID|SSH_BUG_BANNER|
|
||||||
|
SSH_OLD_DHGEX|SSH_BUG_NOREKEY },
|
||||||
|
{ "^OpenSSH_2\\.3\\.0", SSH_BUG_BANNER|SSH_BUG_BIGENDIANAES|
|
||||||
|
SSH_OLD_DHGEX|SSH_BUG_NOREKEY},
|
||||||
|
{ "^OpenSSH_2\\.3\\.", SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
|
||||||
|
SSH_BUG_NOREKEY},
|
||||||
|
{ "^OpenSSH_2\\.5\\.[01]p1",
|
||||||
|
SSH_BUG_BIGENDIANAES|SSH_OLD_DHGEX|
|
||||||
|
SSH_BUG_NOREKEY },
|
||||||
|
{ "^OpenSSH_2\\.5\\.[012]",
|
||||||
|
SSH_OLD_DHGEX|SSH_BUG_NOREKEY },
|
||||||
|
{ "^OpenSSH_2\\.5\\.3",
|
||||||
|
SSH_BUG_NOREKEY },
|
||||||
|
{ "^OpenSSH", 0 },
|
||||||
{ "MindTerm", 0 },
|
{ "MindTerm", 0 },
|
||||||
{ "^2\\.1\\.0 ", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
|
{ "^2\\.1\\.0", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
|
||||||
SSH_OLD_SESSIONID },
|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
|
||||||
|
SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE },
|
||||||
|
{ "^2\\.1 ", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
|
||||||
|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
|
||||||
|
SSH_BUG_RSASIGMD5|SSH_BUG_HBSERVICE },
|
||||||
|
{ "^2\\.0\\.1[3-9]", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
|
||||||
|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
|
||||||
|
SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
|
||||||
|
SSH_BUG_PKOK|SSH_BUG_RSASIGMD5|
|
||||||
|
SSH_BUG_HBSERVICE },
|
||||||
{ "^2\\.0\\.", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
|
{ "^2\\.0\\.", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
|
||||||
SSH_OLD_SESSIONID|
|
SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
|
||||||
SSH_BUG_PUBKEYAUTH|SSH_BUG_X11FWD },
|
SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
|
||||||
{ "^2\\.[23]\\.0 ", SSH_BUG_HMAC},
|
SSH_BUG_PKAUTH|SSH_BUG_PKOK|
|
||||||
|
SSH_BUG_RSASIGMD5 },
|
||||||
|
{ "^2\\.[23]\\.0", SSH_BUG_HMAC|SSH_BUG_RSASIGMD5 },
|
||||||
|
{ "^2\\.3\\.", SSH_BUG_RSASIGMD5 },
|
||||||
{ "^2\\.[2-9]\\.", 0 },
|
{ "^2\\.[2-9]\\.", 0 },
|
||||||
{ "^2\\.4$", SSH_OLD_SESSIONID}, /* Van Dyke */
|
{ "^2\\.4$", SSH_OLD_SESSIONID }, /* Van Dyke */
|
||||||
{ "^3\\.0 SecureCRT", SSH_OLD_SESSIONID},
|
{ "^3\\.0 SecureCRT", SSH_OLD_SESSIONID },
|
||||||
{ "^1\\.7 SecureFX", SSH_OLD_SESSIONID},
|
{ "^1\\.7 SecureFX", SSH_OLD_SESSIONID },
|
||||||
{ "^1\\.2\\.1[89]", SSH_BUG_IGNOREMSG},
|
{ "^1\\.2\\.1[89]", SSH_BUG_IGNOREMSG },
|
||||||
{ "^1\\.2\\.2[012]", SSH_BUG_IGNOREMSG},
|
{ "^1\\.2\\.2[012]", SSH_BUG_IGNOREMSG },
|
||||||
{ "^2\\.", SSH_BUG_HMAC}, /* XXX fallback */
|
{ "^1\\.3\\.2", SSH_BUG_IGNOREMSG }, /* f-secure */
|
||||||
|
{ "^SSH Compatible Server", /* Netscreen */
|
||||||
|
SSH_BUG_PASSWORDPAD },
|
||||||
|
{ "^OSU_0", SSH_BUG_PASSWORDPAD },
|
||||||
|
{ "^OSU_1\\.[0-4]", SSH_BUG_PASSWORDPAD },
|
||||||
|
{ "^OSU_1\\.5alpha[1-3]",
|
||||||
|
SSH_BUG_PASSWORDPAD },
|
||||||
|
{ "^SSH_Version_Mapper",
|
||||||
|
SSH_BUG_SCANNER },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
/* process table, return first match */
|
/* process table, return first match */
|
||||||
@ -89,7 +123,7 @@ compat_datafellows(const char *version)
|
|||||||
ret = regexec(®, version, 0, NULL, 0);
|
ret = regexec(®, version, 0, NULL, 0);
|
||||||
regfree(®);
|
regfree(®);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
debug("match: %s pat %s\n", version, check[i].pat);
|
debug("match: %s pat %s", version, check[i].pat);
|
||||||
datafellows = check[i].bugs;
|
datafellows = check[i].bugs;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -125,3 +159,33 @@ proto_spec(const char *spec)
|
|||||||
xfree(s);
|
xfree(s);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
compat_cipher_proposal(char *cipher_prop)
|
||||||
|
{
|
||||||
|
char *orig_prop, *fix_ciphers;
|
||||||
|
char *cp, *tmp;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (!(datafellows & SSH_BUG_BIGENDIANAES))
|
||||||
|
return(cipher_prop);
|
||||||
|
|
||||||
|
len = strlen(cipher_prop) + 1;
|
||||||
|
fix_ciphers = xmalloc(len);
|
||||||
|
*fix_ciphers = '\0';
|
||||||
|
tmp = orig_prop = xstrdup(cipher_prop);
|
||||||
|
while((cp = strsep(&tmp, ",")) != NULL) {
|
||||||
|
if (strncmp(cp, "aes", 3) && strncmp(cp, "rijndael", 8)) {
|
||||||
|
if (*fix_ciphers)
|
||||||
|
strlcat(fix_ciphers, ",", len);
|
||||||
|
strlcat(fix_ciphers, cp, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xfree(orig_prop);
|
||||||
|
debug2("Original cipher proposal: %s", cipher_prop);
|
||||||
|
debug2("Compat cipher proposal: %s", fix_ciphers);
|
||||||
|
if (!*fix_ciphers)
|
||||||
|
fatal("No available ciphers found.");
|
||||||
|
|
||||||
|
return(fix_ciphers);
|
||||||
|
}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
/* RCSID("$FreeBSD$"); */
|
/* RCSID("$FreeBSD$"); */
|
||||||
/* RCSID("$OpenBSD: compat.h,v 1.11 2000/10/14 12:16:56 markus Exp $"); */
|
/* RCSID("$OpenBSD: compat.h,v 1.23 2001/04/12 19:15:24 markus Exp $"); */
|
||||||
|
|
||||||
#ifndef COMPAT_H
|
#ifndef COMPAT_H
|
||||||
#define COMPAT_H
|
#define COMPAT_H
|
||||||
@ -32,17 +32,29 @@
|
|||||||
#define SSH_PROTO_1_PREFERRED 0x02
|
#define SSH_PROTO_1_PREFERRED 0x02
|
||||||
#define SSH_PROTO_2 0x04
|
#define SSH_PROTO_2 0x04
|
||||||
|
|
||||||
#define SSH_BUG_SIGBLOB 0x01
|
#define SSH_BUG_SIGBLOB 0x0001
|
||||||
#define SSH_BUG_PUBKEYAUTH 0x02
|
#define SSH_BUG_PKSERVICE 0x0002
|
||||||
#define SSH_BUG_HMAC 0x04
|
#define SSH_BUG_HMAC 0x0004
|
||||||
#define SSH_BUG_X11FWD 0x08
|
#define SSH_BUG_X11FWD 0x0008
|
||||||
#define SSH_OLD_SESSIONID 0x10
|
#define SSH_OLD_SESSIONID 0x0010
|
||||||
#define SSH_BUG_IGNOREMSG 0x20
|
#define SSH_BUG_PKAUTH 0x0020
|
||||||
|
#define SSH_BUG_DEBUG 0x0040
|
||||||
|
#define SSH_BUG_BANNER 0x0080
|
||||||
|
#define SSH_BUG_IGNOREMSG 0x0100
|
||||||
|
#define SSH_BUG_PKOK 0x0200
|
||||||
|
#define SSH_BUG_PASSWORDPAD 0x0400
|
||||||
|
#define SSH_BUG_SCANNER 0x0800
|
||||||
|
#define SSH_BUG_BIGENDIANAES 0x1000
|
||||||
|
#define SSH_BUG_RSASIGMD5 0x2000
|
||||||
|
#define SSH_OLD_DHGEX 0x4000
|
||||||
|
#define SSH_BUG_NOREKEY 0x8000
|
||||||
|
#define SSH_BUG_HBSERVICE 0x10000
|
||||||
|
|
||||||
void enable_compat13(void);
|
void enable_compat13(void);
|
||||||
void enable_compat20(void);
|
void enable_compat20(void);
|
||||||
void compat_datafellows(const char *s);
|
void compat_datafellows(const char *s);
|
||||||
int proto_spec(const char *spec);
|
int proto_spec(const char *spec);
|
||||||
|
char *compat_cipher_proposal(char *cipher_prop);
|
||||||
extern int compat13;
|
extern int compat13;
|
||||||
extern int compat20;
|
extern int compat20;
|
||||||
extern int datafellows;
|
extern int datafellows;
|
||||||
|
@ -36,16 +36,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: hostfile.c,v 1.20 2000/09/07 20:27:51 deraadt Exp $");
|
RCSID("$OpenBSD: hostfile.c,v 1.26 2001/04/12 19:15:24 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
#include "ssh.h"
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the
|
* Parses an RSA (number of bits, e, n) or DSA key from a string. Moves the
|
||||||
@ -53,17 +51,15 @@ RCSID("$FreeBSD$");
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
|
hostfile_read_key(char **cpp, u_int *bitsp, Key *ret)
|
||||||
{
|
{
|
||||||
unsigned int bits;
|
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
/* Skip leading whitespace. */
|
/* Skip leading whitespace. */
|
||||||
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
|
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
|
||||||
;
|
;
|
||||||
|
|
||||||
bits = key_read(ret, &cp);
|
if (key_read(ret, &cp) != 1)
|
||||||
if (bits == 0)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Skip trailing whitespace. */
|
/* Skip trailing whitespace. */
|
||||||
@ -72,14 +68,14 @@ hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
|
|||||||
|
|
||||||
/* Return results. */
|
/* Return results. */
|
||||||
*cpp = cp;
|
*cpp = cp;
|
||||||
*bitsp = bits;
|
*bitsp = key_size(ret);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
|
auth_rsa_read_key(char **cpp, u_int *bitsp, BIGNUM * e, BIGNUM * n)
|
||||||
{
|
{
|
||||||
Key *k = key_new(KEY_RSA);
|
Key *k = key_new(KEY_RSA1);
|
||||||
int ret = hostfile_read_key(cpp, bitsp, k);
|
int ret = hostfile_read_key(cpp, bitsp, k);
|
||||||
BN_copy(e, k->rsa->e);
|
BN_copy(e, k->rsa->e);
|
||||||
BN_copy(n, k->rsa->n);
|
BN_copy(n, k->rsa->n);
|
||||||
@ -90,7 +86,7 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
|
|||||||
int
|
int
|
||||||
hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
|
hostfile_check_key(int bits, Key *key, const char *host, const char *filename, int linenum)
|
||||||
{
|
{
|
||||||
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL)
|
if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
if (bits != BN_num_bits(key->rsa->n)) {
|
if (bits != BN_num_bits(key->rsa->n)) {
|
||||||
log("Warning: %s, line %d: keysize mismatch for host %s: "
|
log("Warning: %s, line %d: keysize mismatch for host %s: "
|
||||||
@ -110,15 +106,17 @@ hostfile_check_key(int bits, Key *key, const char *host, const char *filename, i
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HostStatus
|
HostStatus
|
||||||
check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *found)
|
check_host_in_hostfile(const char *filename, const char *host, Key *key,
|
||||||
|
Key *found, int *numret)
|
||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char line[8192];
|
char line[8192];
|
||||||
int linenum = 0;
|
int linenum = 0;
|
||||||
unsigned int kbits, hostlen;
|
u_int kbits;
|
||||||
char *cp, *cp2;
|
char *cp, *cp2;
|
||||||
HostStatus end_return;
|
HostStatus end_return;
|
||||||
|
|
||||||
|
debug3("check_host_in_hostfile: filename %s", filename);
|
||||||
if (key == NULL)
|
if (key == NULL)
|
||||||
fatal("no key to look up");
|
fatal("no key to look up");
|
||||||
/* Open the file containing the list of known hosts. */
|
/* Open the file containing the list of known hosts. */
|
||||||
@ -126,9 +124,6 @@ check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *fo
|
|||||||
if (!f)
|
if (!f)
|
||||||
return HOST_NEW;
|
return HOST_NEW;
|
||||||
|
|
||||||
/* Cache the length of the host name. */
|
|
||||||
hostlen = strlen(host);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return value when the loop terminates. This is set to
|
* Return value when the loop terminates. This is set to
|
||||||
* HOST_CHANGED if we have seen a different key for the host and have
|
* HOST_CHANGED if we have seen a different key for the host and have
|
||||||
@ -136,7 +131,7 @@ check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *fo
|
|||||||
*/
|
*/
|
||||||
end_return = HOST_NEW;
|
end_return = HOST_NEW;
|
||||||
|
|
||||||
/* Go trough the file. */
|
/* Go through the file. */
|
||||||
while (fgets(line, sizeof(line), f)) {
|
while (fgets(line, sizeof(line), f)) {
|
||||||
cp = line;
|
cp = line;
|
||||||
linenum++;
|
linenum++;
|
||||||
@ -152,7 +147,7 @@ check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *fo
|
|||||||
;
|
;
|
||||||
|
|
||||||
/* Check if the host name matches. */
|
/* Check if the host name matches. */
|
||||||
if (match_hostname(host, cp, (unsigned int) (cp2 - cp)) != 1)
|
if (match_hostname(host, cp, (u_int) (cp2 - cp)) != 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Got a match. Skip host name. */
|
/* Got a match. Skip host name. */
|
||||||
@ -167,9 +162,13 @@ check_host_in_hostfile(const char *filename, const char *host, Key *key, Key *fo
|
|||||||
if (!hostfile_check_key(kbits, found, host, filename, linenum))
|
if (!hostfile_check_key(kbits, found, host, filename, linenum))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (numret != NULL)
|
||||||
|
*numret = linenum;
|
||||||
|
|
||||||
/* Check if the current key is the same as the given key. */
|
/* Check if the current key is the same as the given key. */
|
||||||
if (key_equal(key, found)) {
|
if (key_equal(key, found)) {
|
||||||
/* Ok, they match. */
|
/* Ok, they match. */
|
||||||
|
debug3("check_host_in_hostfile: match line %d", linenum);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return HOST_OK;
|
return HOST_OK;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
/* $OpenBSD: includes.h,v 1.14 2001/01/29 01:58:16 niklas Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -31,21 +31,21 @@
|
|||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
#include "ssh.h"
|
RCSID("$OpenBSD: key.c,v 1.25 2001/04/17 10:53:24 markus Exp $");
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "key.h"
|
|
||||||
#include "dsa.h"
|
|
||||||
#include "uuencode.h"
|
|
||||||
|
|
||||||
RCSID("$OpenBSD: key.c,v 1.11 2000/09/07 20:27:51 deraadt Exp $");
|
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#define SSH_DSS "ssh-dss"
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "rsa.h"
|
||||||
|
#include "ssh-dss.h"
|
||||||
|
#include "ssh-rsa.h"
|
||||||
|
#include "uuencode.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "bufaux.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
Key *
|
Key *
|
||||||
key_new(int type)
|
key_new(int type)
|
||||||
@ -58,6 +58,7 @@ key_new(int type)
|
|||||||
k->dsa = NULL;
|
k->dsa = NULL;
|
||||||
k->rsa = NULL;
|
k->rsa = NULL;
|
||||||
switch (k->type) {
|
switch (k->type) {
|
||||||
|
case KEY_RSA1:
|
||||||
case KEY_RSA:
|
case KEY_RSA:
|
||||||
rsa = RSA_new();
|
rsa = RSA_new();
|
||||||
rsa->n = BN_new();
|
rsa->n = BN_new();
|
||||||
@ -72,7 +73,7 @@ key_new(int type)
|
|||||||
dsa->pub_key = BN_new();
|
dsa->pub_key = BN_new();
|
||||||
k->dsa = dsa;
|
k->dsa = dsa;
|
||||||
break;
|
break;
|
||||||
case KEY_EMPTY:
|
case KEY_UNSPEC:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fatal("key_new: bad key type %d", k->type);
|
fatal("key_new: bad key type %d", k->type);
|
||||||
@ -80,10 +81,35 @@ key_new(int type)
|
|||||||
}
|
}
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
Key *
|
||||||
|
key_new_private(int type)
|
||||||
|
{
|
||||||
|
Key *k = key_new(type);
|
||||||
|
switch (k->type) {
|
||||||
|
case KEY_RSA1:
|
||||||
|
case KEY_RSA:
|
||||||
|
k->rsa->d = BN_new();
|
||||||
|
k->rsa->iqmp = BN_new();
|
||||||
|
k->rsa->q = BN_new();
|
||||||
|
k->rsa->p = BN_new();
|
||||||
|
k->rsa->dmq1 = BN_new();
|
||||||
|
k->rsa->dmp1 = BN_new();
|
||||||
|
break;
|
||||||
|
case KEY_DSA:
|
||||||
|
k->dsa->priv_key = BN_new();
|
||||||
|
break;
|
||||||
|
case KEY_UNSPEC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return k;
|
||||||
|
}
|
||||||
void
|
void
|
||||||
key_free(Key *k)
|
key_free(Key *k)
|
||||||
{
|
{
|
||||||
switch (k->type) {
|
switch (k->type) {
|
||||||
|
case KEY_RSA1:
|
||||||
case KEY_RSA:
|
case KEY_RSA:
|
||||||
if (k->rsa != NULL)
|
if (k->rsa != NULL)
|
||||||
RSA_free(k->rsa);
|
RSA_free(k->rsa);
|
||||||
@ -94,6 +120,8 @@ key_free(Key *k)
|
|||||||
DSA_free(k->dsa);
|
DSA_free(k->dsa);
|
||||||
k->dsa = NULL;
|
k->dsa = NULL;
|
||||||
break;
|
break;
|
||||||
|
case KEY_UNSPEC:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fatal("key_free: bad key type %d", k->type);
|
fatal("key_free: bad key type %d", k->type);
|
||||||
break;
|
break;
|
||||||
@ -106,6 +134,7 @@ key_equal(Key *a, Key *b)
|
|||||||
if (a == NULL || b == NULL || a->type != b->type)
|
if (a == NULL || b == NULL || a->type != b->type)
|
||||||
return 0;
|
return 0;
|
||||||
switch (a->type) {
|
switch (a->type) {
|
||||||
|
case KEY_RSA1:
|
||||||
case KEY_RSA:
|
case KEY_RSA:
|
||||||
return a->rsa != NULL && b->rsa != NULL &&
|
return a->rsa != NULL && b->rsa != NULL &&
|
||||||
BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
|
BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
|
||||||
@ -125,20 +154,31 @@ key_equal(Key *a, Key *b)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
u_char*
|
||||||
* Generate key fingerprint in ascii format.
|
key_fingerprint_raw(Key *k, enum fp_type dgst_type, size_t *dgst_raw_length)
|
||||||
* Based on ideas and code from Bjoern Groenvall <bg@sics.se>
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
key_fingerprint(Key *k)
|
|
||||||
{
|
{
|
||||||
static char retval[(EVP_MAX_MD_SIZE+1)*3];
|
EVP_MD *md = NULL;
|
||||||
unsigned char *blob = NULL;
|
EVP_MD_CTX ctx;
|
||||||
|
u_char *blob = NULL;
|
||||||
|
u_char *retval = NULL;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int nlen, elen;
|
int nlen, elen;
|
||||||
|
|
||||||
|
*dgst_raw_length = 0;
|
||||||
|
|
||||||
|
switch (dgst_type) {
|
||||||
|
case SSH_FP_MD5:
|
||||||
|
md = EVP_md5();
|
||||||
|
break;
|
||||||
|
case SSH_FP_SHA1:
|
||||||
|
md = EVP_sha1();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("key_fingerprint_raw: bad digest type %d",
|
||||||
|
dgst_type);
|
||||||
|
}
|
||||||
switch (k->type) {
|
switch (k->type) {
|
||||||
case KEY_RSA:
|
case KEY_RSA1:
|
||||||
nlen = BN_num_bytes(k->rsa->n);
|
nlen = BN_num_bytes(k->rsa->n);
|
||||||
elen = BN_num_bytes(k->rsa->e);
|
elen = BN_num_bytes(k->rsa->e);
|
||||||
len = nlen + elen;
|
len = nlen + elen;
|
||||||
@ -147,34 +187,121 @@ key_fingerprint(Key *k)
|
|||||||
BN_bn2bin(k->rsa->e, blob + nlen);
|
BN_bn2bin(k->rsa->e, blob + nlen);
|
||||||
break;
|
break;
|
||||||
case KEY_DSA:
|
case KEY_DSA:
|
||||||
dsa_make_key_blob(k, &blob, &len);
|
case KEY_RSA:
|
||||||
|
key_to_blob(k, &blob, &len);
|
||||||
|
break;
|
||||||
|
case KEY_UNSPEC:
|
||||||
|
return retval;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fatal("key_fingerprint: bad key type %d", k->type);
|
fatal("key_fingerprint_raw: bad key type %d", k->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
retval[0] = '\0';
|
|
||||||
|
|
||||||
if (blob != NULL) {
|
if (blob != NULL) {
|
||||||
int i;
|
retval = xmalloc(EVP_MAX_MD_SIZE);
|
||||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
|
||||||
EVP_MD *md = EVP_md5();
|
|
||||||
EVP_MD_CTX ctx;
|
|
||||||
EVP_DigestInit(&ctx, md);
|
EVP_DigestInit(&ctx, md);
|
||||||
EVP_DigestUpdate(&ctx, blob, len);
|
EVP_DigestUpdate(&ctx, blob, len);
|
||||||
EVP_DigestFinal(&ctx, digest, NULL);
|
EVP_DigestFinal(&ctx, retval, NULL);
|
||||||
for(i = 0; i < md->md_size; i++) {
|
*dgst_raw_length = md->md_size;
|
||||||
char hex[4];
|
|
||||||
snprintf(hex, sizeof(hex), "%02x:", digest[i]);
|
|
||||||
strlcat(retval, hex, sizeof(retval));
|
|
||||||
}
|
|
||||||
retval[strlen(retval) - 1] = '\0';
|
|
||||||
memset(blob, 0, len);
|
memset(blob, 0, len);
|
||||||
xfree(blob);
|
xfree(blob);
|
||||||
|
} else {
|
||||||
|
fatal("key_fingerprint_raw: blob is null");
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
key_fingerprint_hex(u_char* dgst_raw, size_t dgst_raw_len)
|
||||||
|
{
|
||||||
|
char *retval;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
retval = xmalloc(dgst_raw_len * 3 + 1);
|
||||||
|
retval[0] = '\0';
|
||||||
|
for(i = 0; i < dgst_raw_len; i++) {
|
||||||
|
char hex[4];
|
||||||
|
snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
|
||||||
|
strlcat(retval, hex, dgst_raw_len * 3);
|
||||||
|
}
|
||||||
|
retval[(dgst_raw_len * 3) - 1] = '\0';
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
key_fingerprint_bubblebabble(u_char* dgst_raw, size_t dgst_raw_len)
|
||||||
|
{
|
||||||
|
char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
|
||||||
|
char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
|
||||||
|
'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
|
||||||
|
u_int i, j = 0, rounds, seed = 1;
|
||||||
|
char *retval;
|
||||||
|
|
||||||
|
rounds = (dgst_raw_len / 2) + 1;
|
||||||
|
retval = xmalloc(sizeof(char) * (rounds*6));
|
||||||
|
retval[j++] = 'x';
|
||||||
|
for (i = 0; i < rounds; i++) {
|
||||||
|
u_int idx0, idx1, idx2, idx3, idx4;
|
||||||
|
if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
|
||||||
|
idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
|
||||||
|
seed) % 6;
|
||||||
|
idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
|
||||||
|
idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
|
||||||
|
(seed / 6)) % 6;
|
||||||
|
retval[j++] = vowels[idx0];
|
||||||
|
retval[j++] = consonants[idx1];
|
||||||
|
retval[j++] = vowels[idx2];
|
||||||
|
if ((i + 1) < rounds) {
|
||||||
|
idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
|
||||||
|
idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
|
||||||
|
retval[j++] = consonants[idx3];
|
||||||
|
retval[j++] = '-';
|
||||||
|
retval[j++] = consonants[idx4];
|
||||||
|
seed = ((seed * 5) +
|
||||||
|
((((u_int)(dgst_raw[2 * i])) * 7) +
|
||||||
|
((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
idx0 = seed % 6;
|
||||||
|
idx1 = 16;
|
||||||
|
idx2 = seed / 6;
|
||||||
|
retval[j++] = vowels[idx0];
|
||||||
|
retval[j++] = consonants[idx1];
|
||||||
|
retval[j++] = vowels[idx2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval[j++] = 'x';
|
||||||
|
retval[j++] = '\0';
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
key_fingerprint(Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
|
||||||
|
{
|
||||||
|
char *retval = NULL;
|
||||||
|
u_char *dgst_raw;
|
||||||
|
size_t dgst_raw_len;
|
||||||
|
|
||||||
|
dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
|
||||||
|
if (!dgst_raw)
|
||||||
|
fatal("key_fingerprint: null from key_fingerprint_raw()");
|
||||||
|
switch(dgst_rep) {
|
||||||
|
case SSH_FP_HEX:
|
||||||
|
retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
|
||||||
|
break;
|
||||||
|
case SSH_FP_BUBBLEBABBLE:
|
||||||
|
retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("key_fingerprint_ex: bad digest representation %d",
|
||||||
|
dgst_rep);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(dgst_raw, 0, dgst_raw_len);
|
||||||
|
xfree(dgst_raw);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reads a multiple-precision integer in decimal from the buffer, and advances
|
* Reads a multiple-precision integer in decimal from the buffer, and advances
|
||||||
* the pointer. The integer must already be initialized. This function is
|
* the pointer. The integer must already be initialized. This function is
|
||||||
@ -227,59 +354,109 @@ write_bignum(FILE *f, BIGNUM *num)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fprintf(f, " %s", buf);
|
fprintf(f, " %s", buf);
|
||||||
free(buf);
|
xfree(buf);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
unsigned int
|
|
||||||
|
/* returns 1 ok, -1 error, 0 type mismatch */
|
||||||
|
int
|
||||||
key_read(Key *ret, char **cpp)
|
key_read(Key *ret, char **cpp)
|
||||||
{
|
{
|
||||||
Key *k;
|
Key *k;
|
||||||
unsigned int bits = 0;
|
int success = -1;
|
||||||
char *cp;
|
char *cp, *space;
|
||||||
int len, n;
|
int len, n, type;
|
||||||
unsigned char *blob;
|
u_int bits;
|
||||||
|
u_char *blob;
|
||||||
|
|
||||||
cp = *cpp;
|
cp = *cpp;
|
||||||
|
|
||||||
switch(ret->type) {
|
switch(ret->type) {
|
||||||
case KEY_RSA:
|
case KEY_RSA1:
|
||||||
/* Get number of bits. */
|
/* Get number of bits. */
|
||||||
if (*cp < '0' || *cp > '9')
|
if (*cp < '0' || *cp > '9')
|
||||||
return 0; /* Bad bit count... */
|
return -1; /* Bad bit count... */
|
||||||
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
|
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
|
||||||
bits = 10 * bits + *cp - '0';
|
bits = 10 * bits + *cp - '0';
|
||||||
if (bits == 0)
|
if (bits == 0)
|
||||||
return 0;
|
return -1;
|
||||||
*cpp = cp;
|
*cpp = cp;
|
||||||
/* Get public exponent, public modulus. */
|
/* Get public exponent, public modulus. */
|
||||||
if (!read_bignum(cpp, ret->rsa->e))
|
if (!read_bignum(cpp, ret->rsa->e))
|
||||||
return 0;
|
return -1;
|
||||||
if (!read_bignum(cpp, ret->rsa->n))
|
if (!read_bignum(cpp, ret->rsa->n))
|
||||||
return 0;
|
return -1;
|
||||||
|
success = 1;
|
||||||
break;
|
break;
|
||||||
|
case KEY_UNSPEC:
|
||||||
|
case KEY_RSA:
|
||||||
case KEY_DSA:
|
case KEY_DSA:
|
||||||
if (strncmp(cp, SSH_DSS " ", 7) != 0)
|
space = strchr(cp, ' ');
|
||||||
|
if (space == NULL) {
|
||||||
|
debug3("key_read: no space");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*space = '\0';
|
||||||
|
type = key_type_from_name(cp);
|
||||||
|
*space = ' ';
|
||||||
|
if (type == KEY_UNSPEC) {
|
||||||
|
debug3("key_read: no key found");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cp = space+1;
|
||||||
|
if (*cp == '\0') {
|
||||||
|
debug3("key_read: short string");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (ret->type == KEY_UNSPEC) {
|
||||||
|
ret->type = type;
|
||||||
|
} else if (ret->type != type) {
|
||||||
|
/* is a key, but different type */
|
||||||
|
debug3("key_read: type mismatch");
|
||||||
return 0;
|
return 0;
|
||||||
cp += 7;
|
}
|
||||||
len = 2*strlen(cp);
|
len = 2*strlen(cp);
|
||||||
blob = xmalloc(len);
|
blob = xmalloc(len);
|
||||||
n = uudecode(cp, blob, len);
|
n = uudecode(cp, blob, len);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
error("key_read: uudecode %s failed", cp);
|
error("key_read: uudecode %s failed", cp);
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
k = dsa_key_from_blob(blob, n);
|
k = key_from_blob(blob, n);
|
||||||
if (k == NULL) {
|
if (k == NULL) {
|
||||||
error("key_read: dsa_key_from_blob %s failed", cp);
|
error("key_read: key_from_blob %s failed", cp);
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
xfree(blob);
|
xfree(blob);
|
||||||
if (ret->dsa != NULL)
|
if (k->type != type) {
|
||||||
DSA_free(ret->dsa);
|
error("key_read: type mismatch: encoding error");
|
||||||
ret->dsa = k->dsa;
|
key_free(k);
|
||||||
k->dsa = NULL;
|
return -1;
|
||||||
|
}
|
||||||
|
/*XXXX*/
|
||||||
|
if (ret->type == KEY_RSA) {
|
||||||
|
if (ret->rsa != NULL)
|
||||||
|
RSA_free(ret->rsa);
|
||||||
|
ret->rsa = k->rsa;
|
||||||
|
k->rsa = NULL;
|
||||||
|
success = 1;
|
||||||
|
#ifdef DEBUG_PK
|
||||||
|
RSA_print_fp(stderr, ret->rsa, 8);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
if (ret->dsa != NULL)
|
||||||
|
DSA_free(ret->dsa);
|
||||||
|
ret->dsa = k->dsa;
|
||||||
|
k->dsa = NULL;
|
||||||
|
success = 1;
|
||||||
|
#ifdef DEBUG_PK
|
||||||
|
DSA_print_fp(stderr, ret->dsa, 8);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*XXXX*/
|
||||||
|
if (success != 1)
|
||||||
|
break;
|
||||||
key_free(k);
|
key_free(k);
|
||||||
bits = BN_num_bits(ret->dsa->p);
|
|
||||||
/* advance cp: skip whitespace and data */
|
/* advance cp: skip whitespace and data */
|
||||||
while (*cp == ' ' || *cp == '\t')
|
while (*cp == ' ' || *cp == '\t')
|
||||||
cp++;
|
cp++;
|
||||||
@ -291,15 +468,15 @@ key_read(Key *ret, char **cpp)
|
|||||||
fatal("key_read: bad key type: %d", ret->type);
|
fatal("key_read: bad key type: %d", ret->type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return bits;
|
return success;
|
||||||
}
|
}
|
||||||
int
|
int
|
||||||
key_write(Key *key, FILE *f)
|
key_write(Key *key, FILE *f)
|
||||||
{
|
{
|
||||||
int success = 0;
|
int success = 0;
|
||||||
unsigned int bits = 0;
|
u_int bits = 0;
|
||||||
|
|
||||||
if (key->type == KEY_RSA && key->rsa != NULL) {
|
if (key->type == KEY_RSA1 && key->rsa != NULL) {
|
||||||
/* size of modulus 'n' */
|
/* size of modulus 'n' */
|
||||||
bits = BN_num_bits(key->rsa->n);
|
bits = BN_num_bits(key->rsa->n);
|
||||||
fprintf(f, "%u", bits);
|
fprintf(f, "%u", bits);
|
||||||
@ -309,14 +486,15 @@ key_write(Key *key, FILE *f)
|
|||||||
} else {
|
} else {
|
||||||
error("key_write: failed for RSA key");
|
error("key_write: failed for RSA key");
|
||||||
}
|
}
|
||||||
} else if (key->type == KEY_DSA && key->dsa != NULL) {
|
} else if ((key->type == KEY_DSA && key->dsa != NULL) ||
|
||||||
|
(key->type == KEY_RSA && key->rsa != NULL)) {
|
||||||
int len, n;
|
int len, n;
|
||||||
unsigned char *blob, *uu;
|
u_char *blob, *uu;
|
||||||
dsa_make_key_blob(key, &blob, &len);
|
key_to_blob(key, &blob, &len);
|
||||||
uu = xmalloc(2*len);
|
uu = xmalloc(2*len);
|
||||||
n = uuencode(blob, len, uu, 2*len);
|
n = uuencode(blob, len, uu, 2*len);
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
fprintf(f, "%s %s", SSH_DSS, uu);
|
fprintf(f, "%s %s", key_ssh_name(key), uu);
|
||||||
success = 1;
|
success = 1;
|
||||||
}
|
}
|
||||||
xfree(blob);
|
xfree(blob);
|
||||||
@ -328,6 +506,9 @@ char *
|
|||||||
key_type(Key *k)
|
key_type(Key *k)
|
||||||
{
|
{
|
||||||
switch (k->type) {
|
switch (k->type) {
|
||||||
|
case KEY_RSA1:
|
||||||
|
return "RSA1";
|
||||||
|
break;
|
||||||
case KEY_RSA:
|
case KEY_RSA:
|
||||||
return "RSA";
|
return "RSA";
|
||||||
break;
|
break;
|
||||||
@ -337,9 +518,23 @@ key_type(Key *k)
|
|||||||
}
|
}
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
unsigned int
|
char *
|
||||||
|
key_ssh_name(Key *k)
|
||||||
|
{
|
||||||
|
switch (k->type) {
|
||||||
|
case KEY_RSA:
|
||||||
|
return "ssh-rsa";
|
||||||
|
break;
|
||||||
|
case KEY_DSA:
|
||||||
|
return "ssh-dss";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "ssh-unknown";
|
||||||
|
}
|
||||||
|
u_int
|
||||||
key_size(Key *k){
|
key_size(Key *k){
|
||||||
switch (k->type) {
|
switch (k->type) {
|
||||||
|
case KEY_RSA1:
|
||||||
case KEY_RSA:
|
case KEY_RSA:
|
||||||
return BN_num_bits(k->rsa->n);
|
return BN_num_bits(k->rsa->n);
|
||||||
break;
|
break;
|
||||||
@ -349,3 +544,241 @@ key_size(Key *k){
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RSA *
|
||||||
|
rsa_generate_private_key(u_int bits)
|
||||||
|
{
|
||||||
|
RSA *private;
|
||||||
|
private = RSA_generate_key(bits, 35, NULL, NULL);
|
||||||
|
if (private == NULL)
|
||||||
|
fatal("rsa_generate_private_key: key generation failed.");
|
||||||
|
return private;
|
||||||
|
}
|
||||||
|
|
||||||
|
DSA*
|
||||||
|
dsa_generate_private_key(u_int bits)
|
||||||
|
{
|
||||||
|
DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL);
|
||||||
|
if (private == NULL)
|
||||||
|
fatal("dsa_generate_private_key: DSA_generate_parameters failed");
|
||||||
|
if (!DSA_generate_key(private))
|
||||||
|
fatal("dsa_generate_private_key: DSA_generate_key failed.");
|
||||||
|
if (private == NULL)
|
||||||
|
fatal("dsa_generate_private_key: NULL.");
|
||||||
|
return private;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key *
|
||||||
|
key_generate(int type, u_int bits)
|
||||||
|
{
|
||||||
|
Key *k = key_new(KEY_UNSPEC);
|
||||||
|
switch (type) {
|
||||||
|
case KEY_DSA:
|
||||||
|
k->dsa = dsa_generate_private_key(bits);
|
||||||
|
break;
|
||||||
|
case KEY_RSA:
|
||||||
|
case KEY_RSA1:
|
||||||
|
k->rsa = rsa_generate_private_key(bits);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("key_generate: unknown type %d", type);
|
||||||
|
}
|
||||||
|
k->type = type;
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key *
|
||||||
|
key_from_private(Key *k)
|
||||||
|
{
|
||||||
|
Key *n = NULL;
|
||||||
|
switch (k->type) {
|
||||||
|
case KEY_DSA:
|
||||||
|
n = key_new(k->type);
|
||||||
|
BN_copy(n->dsa->p, k->dsa->p);
|
||||||
|
BN_copy(n->dsa->q, k->dsa->q);
|
||||||
|
BN_copy(n->dsa->g, k->dsa->g);
|
||||||
|
BN_copy(n->dsa->pub_key, k->dsa->pub_key);
|
||||||
|
break;
|
||||||
|
case KEY_RSA:
|
||||||
|
case KEY_RSA1:
|
||||||
|
n = key_new(k->type);
|
||||||
|
BN_copy(n->rsa->n, k->rsa->n);
|
||||||
|
BN_copy(n->rsa->e, k->rsa->e);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fatal("key_from_private: unknown type %d", k->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
key_type_from_name(char *name)
|
||||||
|
{
|
||||||
|
if (strcmp(name, "rsa1") == 0){
|
||||||
|
return KEY_RSA1;
|
||||||
|
} else if (strcmp(name, "rsa") == 0){
|
||||||
|
return KEY_RSA;
|
||||||
|
} else if (strcmp(name, "dsa") == 0){
|
||||||
|
return KEY_DSA;
|
||||||
|
} else if (strcmp(name, "ssh-rsa") == 0){
|
||||||
|
return KEY_RSA;
|
||||||
|
} else if (strcmp(name, "ssh-dss") == 0){
|
||||||
|
return KEY_DSA;
|
||||||
|
}
|
||||||
|
debug2("key_type_from_name: unknown key type '%s'", name);
|
||||||
|
return KEY_UNSPEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
key_names_valid2(const char *names)
|
||||||
|
{
|
||||||
|
char *s, *cp, *p;
|
||||||
|
|
||||||
|
if (names == NULL || strcmp(names, "") == 0)
|
||||||
|
return 0;
|
||||||
|
s = cp = xstrdup(names);
|
||||||
|
for ((p = strsep(&cp, ",")); p && *p != '\0';
|
||||||
|
(p = strsep(&cp, ","))) {
|
||||||
|
switch (key_type_from_name(p)) {
|
||||||
|
case KEY_RSA1:
|
||||||
|
case KEY_UNSPEC:
|
||||||
|
xfree(s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debug3("key names ok: [%s]", names);
|
||||||
|
xfree(s);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key *
|
||||||
|
key_from_blob(char *blob, int blen)
|
||||||
|
{
|
||||||
|
Buffer b;
|
||||||
|
char *ktype;
|
||||||
|
int rlen, type;
|
||||||
|
Key *key = NULL;
|
||||||
|
|
||||||
|
#ifdef DEBUG_PK
|
||||||
|
dump_base64(stderr, blob, blen);
|
||||||
|
#endif
|
||||||
|
buffer_init(&b);
|
||||||
|
buffer_append(&b, blob, blen);
|
||||||
|
ktype = buffer_get_string(&b, NULL);
|
||||||
|
type = key_type_from_name(ktype);
|
||||||
|
|
||||||
|
switch(type){
|
||||||
|
case KEY_RSA:
|
||||||
|
key = key_new(type);
|
||||||
|
buffer_get_bignum2(&b, key->rsa->e);
|
||||||
|
buffer_get_bignum2(&b, key->rsa->n);
|
||||||
|
#ifdef DEBUG_PK
|
||||||
|
RSA_print_fp(stderr, key->rsa, 8);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case KEY_DSA:
|
||||||
|
key = key_new(type);
|
||||||
|
buffer_get_bignum2(&b, key->dsa->p);
|
||||||
|
buffer_get_bignum2(&b, key->dsa->q);
|
||||||
|
buffer_get_bignum2(&b, key->dsa->g);
|
||||||
|
buffer_get_bignum2(&b, key->dsa->pub_key);
|
||||||
|
#ifdef DEBUG_PK
|
||||||
|
DSA_print_fp(stderr, key->dsa, 8);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case KEY_UNSPEC:
|
||||||
|
key = key_new(type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("key_from_blob: cannot handle type %s", ktype);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rlen = buffer_len(&b);
|
||||||
|
if (key != NULL && rlen != 0)
|
||||||
|
error("key_from_blob: remaining bytes in key blob %d", rlen);
|
||||||
|
xfree(ktype);
|
||||||
|
buffer_free(&b);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
key_to_blob(Key *key, u_char **blobp, u_int *lenp)
|
||||||
|
{
|
||||||
|
Buffer b;
|
||||||
|
int len;
|
||||||
|
u_char *buf;
|
||||||
|
|
||||||
|
if (key == NULL) {
|
||||||
|
error("key_to_blob: key == NULL");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
buffer_init(&b);
|
||||||
|
switch(key->type){
|
||||||
|
case KEY_DSA:
|
||||||
|
buffer_put_cstring(&b, key_ssh_name(key));
|
||||||
|
buffer_put_bignum2(&b, key->dsa->p);
|
||||||
|
buffer_put_bignum2(&b, key->dsa->q);
|
||||||
|
buffer_put_bignum2(&b, key->dsa->g);
|
||||||
|
buffer_put_bignum2(&b, key->dsa->pub_key);
|
||||||
|
break;
|
||||||
|
case KEY_RSA:
|
||||||
|
buffer_put_cstring(&b, key_ssh_name(key));
|
||||||
|
buffer_put_bignum2(&b, key->rsa->e);
|
||||||
|
buffer_put_bignum2(&b, key->rsa->n);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("key_to_blob: illegal key type %d", key->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
key_sign(
|
||||||
|
Key *key,
|
||||||
|
u_char **sigp, int *lenp,
|
||||||
|
u_char *data, int datalen)
|
||||||
|
{
|
||||||
|
switch(key->type){
|
||||||
|
case KEY_DSA:
|
||||||
|
return ssh_dss_sign(key, sigp, lenp, data, datalen);
|
||||||
|
break;
|
||||||
|
case KEY_RSA:
|
||||||
|
return ssh_rsa_sign(key, sigp, lenp, data, datalen);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("key_sign: illegal key type %d", key->type);
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
key_verify(
|
||||||
|
Key *key,
|
||||||
|
u_char *signature, int signaturelen,
|
||||||
|
u_char *data, int datalen)
|
||||||
|
{
|
||||||
|
switch(key->type){
|
||||||
|
case KEY_DSA:
|
||||||
|
return ssh_dss_verify(key, signature, signaturelen, data, datalen);
|
||||||
|
break;
|
||||||
|
case KEY_RSA:
|
||||||
|
return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error("key_verify: illegal key type %d", key->type);
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: mpaux.c,v 1.14 2000/09/07 20:27:52 deraadt Exp $");
|
RCSID("$OpenBSD: mpaux.c,v 1.16 2001/02/08 19:30:52 itojun Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
@ -22,16 +22,18 @@ RCSID("$FreeBSD$");
|
|||||||
|
|
||||||
#include <openssl/md5.h>
|
#include <openssl/md5.h>
|
||||||
|
|
||||||
|
#include "mpaux.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
compute_session_id(unsigned char session_id[16],
|
compute_session_id(u_char session_id[16],
|
||||||
unsigned char cookie[8],
|
u_char cookie[8],
|
||||||
BIGNUM* host_key_n,
|
BIGNUM* host_key_n,
|
||||||
BIGNUM* session_key_n)
|
BIGNUM* session_key_n)
|
||||||
{
|
{
|
||||||
unsigned int host_key_bytes = BN_num_bytes(host_key_n);
|
u_int host_key_bytes = BN_num_bytes(host_key_n);
|
||||||
unsigned int session_key_bytes = BN_num_bytes(session_key_n);
|
u_int session_key_bytes = BN_num_bytes(session_key_n);
|
||||||
unsigned int bytes = host_key_bytes + session_key_bytes;
|
u_int bytes = host_key_bytes + session_key_bytes;
|
||||||
unsigned char *buf = xmalloc(bytes);
|
u_char *buf = xmalloc(bytes);
|
||||||
MD5_CTX md;
|
MD5_CTX md;
|
||||||
|
|
||||||
BN_bn2bin(host_key_n, buf);
|
BN_bn2bin(host_key_n, buf);
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: packet.h,v 1.17 2000/09/07 20:27:52 deraadt Exp $"); */
|
/* RCSID("$OpenBSD: packet.h,v 1.22 2001/04/14 16:33:20 stevesk Exp $"); */
|
||||||
/* $FreeBSD$ */
|
/* RCSID("$FreeBSD$"); */
|
||||||
|
|
||||||
#ifndef PACKET_H
|
#ifndef PACKET_H
|
||||||
#define PACKET_H
|
#define PACKET_H
|
||||||
@ -47,17 +47,17 @@ void packet_close(void);
|
|||||||
* encrypted independently of each other. Cipher types are defined in ssh.h.
|
* encrypted independently of each other. Cipher types are defined in ssh.h.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
|
packet_set_encryption_key(const u_char *key, u_int keylen,
|
||||||
int cipher_type);
|
int cipher_type);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sets remote side protocol flags for the current connection. This can be
|
* Sets remote side protocol flags for the current connection. This can be
|
||||||
* called at any time.
|
* called at any time.
|
||||||
*/
|
*/
|
||||||
void packet_set_protocol_flags(unsigned int flags);
|
void packet_set_protocol_flags(u_int flags);
|
||||||
|
|
||||||
/* Returns the remote protocol flags set earlier by the above function. */
|
/* Returns the remote protocol flags set earlier by the above function. */
|
||||||
unsigned int packet_get_protocol_flags(void);
|
u_int packet_get_protocol_flags(void);
|
||||||
|
|
||||||
/* Enables compression in both directions starting from the next packet. */
|
/* Enables compression in both directions starting from the next packet. */
|
||||||
void packet_start_compression(int level);
|
void packet_start_compression(int level);
|
||||||
@ -66,7 +66,7 @@ void packet_start_compression(int level);
|
|||||||
* Informs that the current session is interactive. Sets IP flags for
|
* Informs that the current session is interactive. Sets IP flags for
|
||||||
* optimal performance in interactive use.
|
* optimal performance in interactive use.
|
||||||
*/
|
*/
|
||||||
void packet_set_interactive(int interactive, int keepalives);
|
void packet_set_interactive(int interactive);
|
||||||
|
|
||||||
/* Returns true if the current connection is interactive. */
|
/* Returns true if the current connection is interactive. */
|
||||||
int packet_is_interactive(void);
|
int packet_is_interactive(void);
|
||||||
@ -78,16 +78,16 @@ void packet_start(int type);
|
|||||||
void packet_put_char(int ch);
|
void packet_put_char(int ch);
|
||||||
|
|
||||||
/* Appends an integer to the packet data. */
|
/* Appends an integer to the packet data. */
|
||||||
void packet_put_int(unsigned int value);
|
void packet_put_int(u_int value);
|
||||||
|
|
||||||
/* Appends an arbitrary precision integer to packet data. */
|
/* Appends an arbitrary precision integer to packet data. */
|
||||||
void packet_put_bignum(BIGNUM * value);
|
void packet_put_bignum(BIGNUM * value);
|
||||||
void packet_put_bignum2(BIGNUM * value);
|
void packet_put_bignum2(BIGNUM * value);
|
||||||
|
|
||||||
/* Appends a string to packet data. */
|
/* Appends a string to packet data. */
|
||||||
void packet_put_string(const char *buf, unsigned int len);
|
void packet_put_string(const char *buf, u_int len);
|
||||||
void packet_put_cstring(const char *str);
|
void packet_put_cstring(const char *str);
|
||||||
void packet_put_raw(const char *buf, unsigned int len);
|
void packet_put_raw(const char *buf, u_int len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finalizes and sends the packet. If the encryption key has been set,
|
* Finalizes and sends the packet. If the encryption key has been set,
|
||||||
@ -118,13 +118,13 @@ int packet_read_poll(int *packet_len_ptr);
|
|||||||
* Buffers the given amount of input characters. This is intended to be used
|
* Buffers the given amount of input characters. This is intended to be used
|
||||||
* together with packet_read_poll.
|
* together with packet_read_poll.
|
||||||
*/
|
*/
|
||||||
void packet_process_incoming(const char *buf, unsigned int len);
|
void packet_process_incoming(const char *buf, u_int len);
|
||||||
|
|
||||||
/* Returns a character (0-255) from the packet data. */
|
/* Returns a character (0-255) from the packet data. */
|
||||||
unsigned int packet_get_char(void);
|
u_int packet_get_char(void);
|
||||||
|
|
||||||
/* Returns an integer from the packet data. */
|
/* Returns an integer from the packet data. */
|
||||||
unsigned int packet_get_int(void);
|
u_int packet_get_int(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns an arbitrary precision integer from the packet data. The integer
|
* Returns an arbitrary precision integer from the packet data. The integer
|
||||||
@ -140,7 +140,7 @@ char *packet_get_raw(int *length_ptr);
|
|||||||
* no longer needed. The length_ptr argument may be NULL, or point to an
|
* no longer needed. The length_ptr argument may be NULL, or point to an
|
||||||
* integer into which the length of the string is stored.
|
* integer into which the length of the string is stored.
|
||||||
*/
|
*/
|
||||||
char *packet_get_string(unsigned int *length_ptr);
|
char *packet_get_string(u_int *length_ptr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
|
* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
|
||||||
@ -179,8 +179,8 @@ extern int max_packet_size;
|
|||||||
int packet_set_maxsize(int s);
|
int packet_set_maxsize(int s);
|
||||||
#define packet_get_maxsize() max_packet_size
|
#define packet_get_maxsize() max_packet_size
|
||||||
|
|
||||||
/* Stores tty modes from the fd into current packet. */
|
/* Stores tty modes from the fd or tiop into current packet. */
|
||||||
void tty_make_modes(int fd);
|
void tty_make_modes(int fd, struct termios *tiop);
|
||||||
|
|
||||||
/* Parses tty modes for the fd from the current packet. */
|
/* Parses tty modes for the fd from the current packet. */
|
||||||
void tty_parse_modes(int fd, int *n_bytes_ptr);
|
void tty_parse_modes(int fd, int *n_bytes_ptr);
|
||||||
@ -215,4 +215,10 @@ void packet_set_ssh2_format(void);
|
|||||||
/* returns remaining payload bytes */
|
/* returns remaining payload bytes */
|
||||||
int packet_remaining(void);
|
int packet_remaining(void);
|
||||||
|
|
||||||
|
/* append an ignore message */
|
||||||
|
void packet_send_ignore(int nbytes);
|
||||||
|
|
||||||
|
/* add an ignore message and make sure size (current+ignore) = n*sumlen */
|
||||||
|
void packet_inject_ignore(int sumlen);
|
||||||
|
|
||||||
#endif /* PACKET_H */
|
#endif /* PACKET_H */
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
/* $OpenBSD: pathnames.h,v 1.5 2001/04/12 19:15:24 markus Exp $ */
|
/* $OpenBSD: pathnames.h,v 1.5 2001/04/12 19:15:24 markus Exp $ */
|
||||||
|
/* $FreeBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -12,7 +13,7 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ETCDIR "/etc"
|
#define ETCDIR "/etc/ssh"
|
||||||
#define _PATH_SSH_PIDDIR "/var/run"
|
#define _PATH_SSH_PIDDIR "/var/run"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -12,14 +12,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: readconf.c,v 1.49 2000/10/11 20:27:23 markus Exp $");
|
RCSID("$OpenBSD: readconf.c,v 1.76 2001/04/17 10:53:25 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "readconf.h"
|
|
||||||
#include "match.h"
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "cipher.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "readconf.h"
|
||||||
|
#include "match.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "kex.h"
|
||||||
|
#include "mac.h"
|
||||||
|
|
||||||
/* Format of the configuration file:
|
/* Format of the configuration file:
|
||||||
|
|
||||||
@ -69,7 +75,7 @@ RCSID("$FreeBSD$");
|
|||||||
# Defaults for various options
|
# Defaults for various options
|
||||||
Host *
|
Host *
|
||||||
ForwardAgent no
|
ForwardAgent no
|
||||||
ForwardX11 yes
|
ForwardX11 no
|
||||||
RhostsAuthentication yes
|
RhostsAuthentication yes
|
||||||
PasswordAuthentication yes
|
PasswordAuthentication yes
|
||||||
RSAAuthentication yes
|
RSAAuthentication yes
|
||||||
@ -90,7 +96,7 @@ typedef enum {
|
|||||||
oBadOption,
|
oBadOption,
|
||||||
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
|
oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
|
||||||
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
|
oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
|
||||||
oSkeyAuthentication, oXAuthLocation,
|
oChallengeResponseAuthentication, oXAuthLocation,
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
oKerberosAuthentication,
|
oKerberosAuthentication,
|
||||||
#endif /* KRB4 */
|
#endif /* KRB4 */
|
||||||
@ -104,10 +110,12 @@ typedef enum {
|
|||||||
oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
|
oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
|
||||||
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
|
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
|
||||||
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
|
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
|
||||||
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
|
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
|
||||||
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
|
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
|
||||||
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication,
|
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
|
||||||
oKbdInteractiveAuthentication, oKbdInteractiveDevices
|
oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
|
||||||
|
oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
|
||||||
|
oHostKeyAlgorithms
|
||||||
} OpCodes;
|
} OpCodes;
|
||||||
|
|
||||||
/* Textual representations of the tokens. */
|
/* Textual representations of the tokens. */
|
||||||
@ -126,8 +134,13 @@ static struct {
|
|||||||
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
|
{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
|
||||||
{ "kbdinteractivedevices", oKbdInteractiveDevices },
|
{ "kbdinteractivedevices", oKbdInteractiveDevices },
|
||||||
{ "rsaauthentication", oRSAAuthentication },
|
{ "rsaauthentication", oRSAAuthentication },
|
||||||
{ "dsaauthentication", oDSAAuthentication },
|
{ "pubkeyauthentication", oPubkeyAuthentication },
|
||||||
{ "skeyauthentication", oSkeyAuthentication },
|
{ "dsaauthentication", oPubkeyAuthentication }, /* alias */
|
||||||
|
{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
|
||||||
|
{ "hostbasedauthentication", oHostbasedAuthentication },
|
||||||
|
{ "challengeresponseauthentication", oChallengeResponseAuthentication },
|
||||||
|
{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
|
||||||
|
{ "tisauthentication", oChallengeResponseAuthentication }, /* alias */
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
{ "kerberosauthentication", oKerberosAuthentication },
|
{ "kerberosauthentication", oKerberosAuthentication },
|
||||||
#endif /* KRB4 || KRB5 */
|
#endif /* KRB4 || KRB5 */
|
||||||
@ -141,19 +154,20 @@ static struct {
|
|||||||
{ "fallbacktorsh", oFallBackToRsh },
|
{ "fallbacktorsh", oFallBackToRsh },
|
||||||
{ "usersh", oUseRsh },
|
{ "usersh", oUseRsh },
|
||||||
{ "identityfile", oIdentityFile },
|
{ "identityfile", oIdentityFile },
|
||||||
{ "identityfile2", oIdentityFile2 },
|
{ "identityfile2", oIdentityFile }, /* alias */
|
||||||
{ "hostname", oHostName },
|
{ "hostname", oHostName },
|
||||||
|
{ "hostkeyalias", oHostKeyAlias },
|
||||||
{ "proxycommand", oProxyCommand },
|
{ "proxycommand", oProxyCommand },
|
||||||
{ "port", oPort },
|
{ "port", oPort },
|
||||||
{ "cipher", oCipher },
|
{ "cipher", oCipher },
|
||||||
{ "ciphers", oCiphers },
|
{ "ciphers", oCiphers },
|
||||||
|
{ "macs", oMacs },
|
||||||
{ "protocol", oProtocol },
|
{ "protocol", oProtocol },
|
||||||
{ "remoteforward", oRemoteForward },
|
{ "remoteforward", oRemoteForward },
|
||||||
{ "localforward", oLocalForward },
|
{ "localforward", oLocalForward },
|
||||||
{ "user", oUser },
|
{ "user", oUser },
|
||||||
{ "host", oHost },
|
{ "host", oHost },
|
||||||
{ "escapechar", oEscapeChar },
|
{ "escapechar", oEscapeChar },
|
||||||
{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
|
|
||||||
{ "globalknownhostsfile", oGlobalKnownHostsFile },
|
{ "globalknownhostsfile", oGlobalKnownHostsFile },
|
||||||
{ "userknownhostsfile", oUserKnownHostsFile },
|
{ "userknownhostsfile", oUserKnownHostsFile },
|
||||||
{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
|
{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
|
||||||
@ -166,8 +180,10 @@ static struct {
|
|||||||
{ "compressionlevel", oCompressionLevel },
|
{ "compressionlevel", oCompressionLevel },
|
||||||
{ "keepalive", oKeepAlives },
|
{ "keepalive", oKeepAlives },
|
||||||
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
|
{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
|
||||||
{ "tisauthentication", oTISAuthentication },
|
|
||||||
{ "loglevel", oLogLevel },
|
{ "loglevel", oLogLevel },
|
||||||
|
{ "dynamicforward", oDynamicForward },
|
||||||
|
{ "preferredauthentications", oPreferredAuthentications },
|
||||||
|
{ "hostkeyalgorithms", oHostKeyAlgorithms },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -183,7 +199,7 @@ add_local_forward(Options *options, u_short port, const char *host,
|
|||||||
Forward *fwd;
|
Forward *fwd;
|
||||||
extern uid_t original_real_uid;
|
extern uid_t original_real_uid;
|
||||||
if (port < IPPORT_RESERVED && original_real_uid != 0)
|
if (port < IPPORT_RESERVED && original_real_uid != 0)
|
||||||
fatal("Privileged ports can only be forwarded by root.\n");
|
fatal("Privileged ports can only be forwarded by root.");
|
||||||
if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
|
if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
|
||||||
fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
|
fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
|
||||||
fwd = &options->local_forwards[options->num_local_forwards++];
|
fwd = &options->local_forwards[options->num_local_forwards++];
|
||||||
@ -212,21 +228,20 @@ add_remote_forward(Options *options, u_short port, const char *host,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the number of the token pointed to by cp of length len. Never
|
* Returns the number of the token pointed to by cp or oBadOption.
|
||||||
* returns if the token is not known.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static OpCodes
|
static OpCodes
|
||||||
parse_token(const char *cp, const char *filename, int linenum)
|
parse_token(const char *cp, const char *filename, int linenum)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; keywords[i].name; i++)
|
for (i = 0; keywords[i].name; i++)
|
||||||
if (strcasecmp(cp, keywords[i].name) == 0)
|
if (strcasecmp(cp, keywords[i].name) == 0)
|
||||||
return keywords[i].opcode;
|
return keywords[i].opcode;
|
||||||
|
|
||||||
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
|
error("%s: line %d: Bad configuration option: %s",
|
||||||
filename, linenum, cp);
|
filename, linenum, cp);
|
||||||
return oBadOption;
|
return oBadOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +265,7 @@ process_config_line(Options *options, const char *host,
|
|||||||
/* Ignore leading whitespace. */
|
/* Ignore leading whitespace. */
|
||||||
if (*keyword == '\0')
|
if (*keyword == '\0')
|
||||||
keyword = strdelim(&s);
|
keyword = strdelim(&s);
|
||||||
if (!*keyword || *keyword == '\n' || *keyword == '#')
|
if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
opcode = parse_token(keyword, filename, linenum);
|
opcode = parse_token(keyword, filename, linenum);
|
||||||
@ -305,8 +320,8 @@ process_config_line(Options *options, const char *host,
|
|||||||
charptr = &options->kbd_interactive_devices;
|
charptr = &options->kbd_interactive_devices;
|
||||||
goto parse_string;
|
goto parse_string;
|
||||||
|
|
||||||
case oDSAAuthentication:
|
case oPubkeyAuthentication:
|
||||||
intptr = &options->dsa_authentication;
|
intptr = &options->pubkey_authentication;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
case oRSAAuthentication:
|
case oRSAAuthentication:
|
||||||
@ -317,10 +332,8 @@ process_config_line(Options *options, const char *host,
|
|||||||
intptr = &options->rhosts_rsa_authentication;
|
intptr = &options->rhosts_rsa_authentication;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
case oTISAuthentication:
|
case oHostbasedAuthentication:
|
||||||
/* fallthrough, there is no difference on the client side */
|
intptr = &options->hostbased_authentication;
|
||||||
case oSkeyAuthentication:
|
|
||||||
intptr = &options->skey_authentication;
|
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
@ -329,6 +342,10 @@ process_config_line(Options *options, const char *host,
|
|||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
#endif /* KRB4 || KRB5 */
|
#endif /* KRB4 || KRB5 */
|
||||||
|
|
||||||
|
case oChallengeResponseAuthentication:
|
||||||
|
intptr = &options->challenge_reponse_authentication;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
case oKrb5TgtPassing:
|
case oKrb5TgtPassing:
|
||||||
intptr = &options->krb5_tgt_passing;
|
intptr = &options->krb5_tgt_passing;
|
||||||
@ -365,7 +382,7 @@ process_config_line(Options *options, const char *host,
|
|||||||
intptr = &options->strict_host_key_checking;
|
intptr = &options->strict_host_key_checking;
|
||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing yes/no argument.",
|
fatal("%.200s line %d: Missing yes/no/ask argument.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
value = 0; /* To avoid compiler warning... */
|
value = 0; /* To avoid compiler warning... */
|
||||||
if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
|
if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
|
||||||
@ -397,20 +414,15 @@ process_config_line(Options *options, const char *host,
|
|||||||
goto parse_int;
|
goto parse_int;
|
||||||
|
|
||||||
case oIdentityFile:
|
case oIdentityFile:
|
||||||
case oIdentityFile2:
|
|
||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
if (*activep) {
|
if (*activep) {
|
||||||
intptr = (opcode == oIdentityFile) ?
|
intptr = &options->num_identity_files;
|
||||||
&options->num_identity_files :
|
|
||||||
&options->num_identity_files2;
|
|
||||||
if (*intptr >= SSH_MAX_IDENTITY_FILES)
|
if (*intptr >= SSH_MAX_IDENTITY_FILES)
|
||||||
fatal("%.200s line %d: Too many identity files specified (max %d).",
|
fatal("%.200s line %d: Too many identity files specified (max %d).",
|
||||||
filename, linenum, SSH_MAX_IDENTITY_FILES);
|
filename, linenum, SSH_MAX_IDENTITY_FILES);
|
||||||
charptr = (opcode == oIdentityFile) ?
|
charptr = &options->identity_files[*intptr];
|
||||||
&options->identity_files[*intptr] :
|
|
||||||
&options->identity_files2[*intptr];
|
|
||||||
*charptr = xstrdup(arg);
|
*charptr = xstrdup(arg);
|
||||||
*intptr = *intptr + 1;
|
*intptr = *intptr + 1;
|
||||||
}
|
}
|
||||||
@ -450,6 +462,14 @@ process_config_line(Options *options, const char *host,
|
|||||||
charptr = &options->hostname;
|
charptr = &options->hostname;
|
||||||
goto parse_string;
|
goto parse_string;
|
||||||
|
|
||||||
|
case oHostKeyAlias:
|
||||||
|
charptr = &options->host_key_alias;
|
||||||
|
goto parse_string;
|
||||||
|
|
||||||
|
case oPreferredAuthentications:
|
||||||
|
charptr = &options->preferred_authentications;
|
||||||
|
goto parse_string;
|
||||||
|
|
||||||
case oProxyCommand:
|
case oProxyCommand:
|
||||||
charptr = &options->proxy_command;
|
charptr = &options->proxy_command;
|
||||||
string = xstrdup("");
|
string = xstrdup("");
|
||||||
@ -509,6 +529,28 @@ process_config_line(Options *options, const char *host,
|
|||||||
options->ciphers = xstrdup(arg);
|
options->ciphers = xstrdup(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oMacs:
|
||||||
|
arg = strdelim(&s);
|
||||||
|
if (!arg || *arg == '\0')
|
||||||
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
|
if (!mac_valid(arg))
|
||||||
|
fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
|
||||||
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
|
if (*activep && options->macs == NULL)
|
||||||
|
options->macs = xstrdup(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case oHostKeyAlgorithms:
|
||||||
|
arg = strdelim(&s);
|
||||||
|
if (!arg || *arg == '\0')
|
||||||
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
|
if (!key_names_valid2(arg))
|
||||||
|
fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
|
||||||
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
|
if (*activep && options->hostkeyalgorithms == NULL)
|
||||||
|
options->hostkeyalgorithms = xstrdup(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
case oProtocol:
|
case oProtocol:
|
||||||
intptr = &options->protocol;
|
intptr = &options->protocol;
|
||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
@ -527,7 +569,7 @@ process_config_line(Options *options, const char *host,
|
|||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
value = log_level_number(arg);
|
value = log_level_number(arg);
|
||||||
if (value == (LogLevel) - 1)
|
if (value == (LogLevel) - 1)
|
||||||
fatal("%.200s line %d: unsupported log level '%s'\n",
|
fatal("%.200s line %d: unsupported log level '%s'",
|
||||||
filename, linenum, arg ? arg : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*activep && (LogLevel) * intptr == -1)
|
if (*activep && (LogLevel) * intptr == -1)
|
||||||
*intptr = (LogLevel) value;
|
*intptr = (LogLevel) value;
|
||||||
@ -537,10 +579,10 @@ process_config_line(Options *options, const char *host,
|
|||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
if (arg[0] < '0' || arg[0] > '9')
|
fwd_port = a2port(arg);
|
||||||
|
if (fwd_port == 0)
|
||||||
fatal("%.200s line %d: Badly formatted port number.",
|
fatal("%.200s line %d: Badly formatted port number.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
fwd_port = atoi(arg);
|
|
||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing second argument.",
|
fatal("%.200s line %d: Missing second argument.",
|
||||||
@ -556,10 +598,10 @@ process_config_line(Options *options, const char *host,
|
|||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
if (arg[0] < '0' || arg[0] > '9')
|
fwd_port = a2port(arg);
|
||||||
|
if (fwd_port == 0)
|
||||||
fatal("%.200s line %d: Badly formatted port number.",
|
fatal("%.200s line %d: Badly formatted port number.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
fwd_port = atoi(arg);
|
|
||||||
arg = strdelim(&s);
|
arg = strdelim(&s);
|
||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing second argument.",
|
fatal("%.200s line %d: Missing second argument.",
|
||||||
@ -571,6 +613,18 @@ process_config_line(Options *options, const char *host,
|
|||||||
add_local_forward(options, fwd_port, buf, fwd_host_port);
|
add_local_forward(options, fwd_port, buf, fwd_host_port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case oDynamicForward:
|
||||||
|
arg = strdelim(&s);
|
||||||
|
if (!arg || *arg == '\0')
|
||||||
|
fatal("%.200s line %d: Missing port argument.",
|
||||||
|
filename, linenum);
|
||||||
|
fwd_port = a2port(arg);
|
||||||
|
if (fwd_port == 0)
|
||||||
|
fatal("%.200s line %d: Badly formatted port number.",
|
||||||
|
filename, linenum);
|
||||||
|
add_local_forward(options, fwd_port, "socks4", 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case oHost:
|
case oHost:
|
||||||
*activep = 0;
|
*activep = 0;
|
||||||
while ((arg = strdelim(&s)) != NULL && *arg != '\0')
|
while ((arg = strdelim(&s)) != NULL && *arg != '\0')
|
||||||
@ -588,10 +642,10 @@ process_config_line(Options *options, const char *host,
|
|||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0')
|
||||||
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
fatal("%.200s line %d: Missing argument.", filename, linenum);
|
||||||
if (arg[0] == '^' && arg[2] == 0 &&
|
if (arg[0] == '^' && arg[2] == 0 &&
|
||||||
(unsigned char) arg[1] >= 64 && (unsigned char) arg[1] < 128)
|
(u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
|
||||||
value = (unsigned char) arg[1] & 31;
|
value = (u_char) arg[1] & 31;
|
||||||
else if (strlen(arg) == 1)
|
else if (strlen(arg) == 1)
|
||||||
value = (unsigned char) arg[0];
|
value = (u_char) arg[0];
|
||||||
else if (strcmp(arg, "none") == 0)
|
else if (strcmp(arg, "none") == 0)
|
||||||
value = -2;
|
value = -2;
|
||||||
else {
|
else {
|
||||||
@ -609,8 +663,7 @@ process_config_line(Options *options, const char *host,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check that there is no garbage at end of line. */
|
/* Check that there is no garbage at end of line. */
|
||||||
if ((arg = strdelim(&s)) != NULL && *arg != '\0')
|
if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
|
||||||
{
|
|
||||||
fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
|
fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
|
||||||
filename, linenum, arg);
|
filename, linenum, arg);
|
||||||
}
|
}
|
||||||
@ -653,7 +706,7 @@ read_config_file(const char *filename, const char *host, Options *options)
|
|||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (bad_options > 0)
|
if (bad_options > 0)
|
||||||
fatal("%s: terminating, %d bad configuration options\n",
|
fatal("%s: terminating, %d bad configuration options",
|
||||||
filename, bad_options);
|
filename, bad_options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,8 +728,8 @@ initialize_options(Options * options)
|
|||||||
options->use_privileged_port = -1;
|
options->use_privileged_port = -1;
|
||||||
options->rhosts_authentication = -1;
|
options->rhosts_authentication = -1;
|
||||||
options->rsa_authentication = -1;
|
options->rsa_authentication = -1;
|
||||||
options->dsa_authentication = -1;
|
options->pubkey_authentication = -1;
|
||||||
options->skey_authentication = -1;
|
options->challenge_reponse_authentication = -1;
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
options->kerberos_authentication = -1;
|
options->kerberos_authentication = -1;
|
||||||
#endif
|
#endif
|
||||||
@ -691,6 +744,7 @@ initialize_options(Options * options)
|
|||||||
options->kbd_interactive_authentication = -1;
|
options->kbd_interactive_authentication = -1;
|
||||||
options->kbd_interactive_devices = NULL;
|
options->kbd_interactive_devices = NULL;
|
||||||
options->rhosts_rsa_authentication = -1;
|
options->rhosts_rsa_authentication = -1;
|
||||||
|
options->hostbased_authentication = -1;
|
||||||
options->fallback_to_rsh = -1;
|
options->fallback_to_rsh = -1;
|
||||||
options->use_rsh = -1;
|
options->use_rsh = -1;
|
||||||
options->batch_mode = -1;
|
options->batch_mode = -1;
|
||||||
@ -704,10 +758,12 @@ initialize_options(Options * options)
|
|||||||
options->number_of_password_prompts = -1;
|
options->number_of_password_prompts = -1;
|
||||||
options->cipher = -1;
|
options->cipher = -1;
|
||||||
options->ciphers = NULL;
|
options->ciphers = NULL;
|
||||||
|
options->macs = NULL;
|
||||||
|
options->hostkeyalgorithms = NULL;
|
||||||
options->protocol = SSH_PROTO_UNKNOWN;
|
options->protocol = SSH_PROTO_UNKNOWN;
|
||||||
options->num_identity_files = 0;
|
options->num_identity_files = 0;
|
||||||
options->num_identity_files2 = 0;
|
|
||||||
options->hostname = NULL;
|
options->hostname = NULL;
|
||||||
|
options->host_key_alias = NULL;
|
||||||
options->proxy_command = NULL;
|
options->proxy_command = NULL;
|
||||||
options->user = NULL;
|
options->user = NULL;
|
||||||
options->escape_char = -1;
|
options->escape_char = -1;
|
||||||
@ -718,6 +774,7 @@ initialize_options(Options * options)
|
|||||||
options->num_local_forwards = 0;
|
options->num_local_forwards = 0;
|
||||||
options->num_remote_forwards = 0;
|
options->num_remote_forwards = 0;
|
||||||
options->log_level = (LogLevel) - 1;
|
options->log_level = (LogLevel) - 1;
|
||||||
|
options->preferred_authentications = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -728,6 +785,8 @@ initialize_options(Options * options)
|
|||||||
void
|
void
|
||||||
fill_default_options(Options * options)
|
fill_default_options(Options * options)
|
||||||
{
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
if (options->forward_agent == -1)
|
if (options->forward_agent == -1)
|
||||||
options->forward_agent = 0;
|
options->forward_agent = 0;
|
||||||
if (options->forward_x11 == -1)
|
if (options->forward_x11 == -1)
|
||||||
@ -739,15 +798,15 @@ fill_default_options(Options * options)
|
|||||||
if (options->gateway_ports == -1)
|
if (options->gateway_ports == -1)
|
||||||
options->gateway_ports = 0;
|
options->gateway_ports = 0;
|
||||||
if (options->use_privileged_port == -1)
|
if (options->use_privileged_port == -1)
|
||||||
options->use_privileged_port = 1;
|
options->use_privileged_port = 0;
|
||||||
if (options->rhosts_authentication == -1)
|
if (options->rhosts_authentication == -1)
|
||||||
options->rhosts_authentication = 1;
|
options->rhosts_authentication = 1;
|
||||||
if (options->rsa_authentication == -1)
|
if (options->rsa_authentication == -1)
|
||||||
options->rsa_authentication = 1;
|
options->rsa_authentication = 1;
|
||||||
if (options->dsa_authentication == -1)
|
if (options->pubkey_authentication == -1)
|
||||||
options->dsa_authentication = 1;
|
options->pubkey_authentication = 1;
|
||||||
if (options->skey_authentication == -1)
|
if (options->challenge_reponse_authentication == -1)
|
||||||
options->skey_authentication = 0;
|
options->challenge_reponse_authentication = 0;
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
if (options->kerberos_authentication == -1)
|
if (options->kerberos_authentication == -1)
|
||||||
options->kerberos_authentication = 1;
|
options->kerberos_authentication = 1;
|
||||||
@ -765,9 +824,11 @@ fill_default_options(Options * options)
|
|||||||
if (options->password_authentication == -1)
|
if (options->password_authentication == -1)
|
||||||
options->password_authentication = 1;
|
options->password_authentication = 1;
|
||||||
if (options->kbd_interactive_authentication == -1)
|
if (options->kbd_interactive_authentication == -1)
|
||||||
options->kbd_interactive_authentication = 0;
|
options->kbd_interactive_authentication = 1;
|
||||||
if (options->rhosts_rsa_authentication == -1)
|
if (options->rhosts_rsa_authentication == -1)
|
||||||
options->rhosts_rsa_authentication = 1;
|
options->rhosts_rsa_authentication = 1;
|
||||||
|
if (options->hostbased_authentication == -1)
|
||||||
|
options->hostbased_authentication = 0;
|
||||||
if (options->fallback_to_rsh == -1)
|
if (options->fallback_to_rsh == -1)
|
||||||
options->fallback_to_rsh = 0;
|
options->fallback_to_rsh = 0;
|
||||||
if (options->use_rsh == -1)
|
if (options->use_rsh == -1)
|
||||||
@ -794,33 +855,47 @@ fill_default_options(Options * options)
|
|||||||
if (options->cipher == -1)
|
if (options->cipher == -1)
|
||||||
options->cipher = SSH_CIPHER_NOT_SET;
|
options->cipher = SSH_CIPHER_NOT_SET;
|
||||||
/* options->ciphers, default set in myproposals.h */
|
/* options->ciphers, default set in myproposals.h */
|
||||||
|
/* options->macs, default set in myproposals.h */
|
||||||
|
/* options->hostkeyalgorithms, default set in myproposals.h */
|
||||||
if (options->protocol == SSH_PROTO_UNKNOWN)
|
if (options->protocol == SSH_PROTO_UNKNOWN)
|
||||||
options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
|
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
||||||
if (options->num_identity_files == 0) {
|
if (options->num_identity_files == 0) {
|
||||||
options->identity_files[0] =
|
if (options->protocol & SSH_PROTO_1) {
|
||||||
xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
|
len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
|
||||||
sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
|
options->identity_files[options->num_identity_files] =
|
||||||
options->num_identity_files = 1;
|
xmalloc(len);
|
||||||
}
|
snprintf(options->identity_files[options->num_identity_files++],
|
||||||
if (options->num_identity_files2 == 0) {
|
len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
|
||||||
options->identity_files2[0] =
|
}
|
||||||
xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
|
if (options->protocol & SSH_PROTO_2) {
|
||||||
sprintf(options->identity_files2[0], "~/%.100s", SSH_CLIENT_ID_DSA);
|
len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
|
||||||
options->num_identity_files2 = 1;
|
options->identity_files[options->num_identity_files] =
|
||||||
|
xmalloc(len);
|
||||||
|
snprintf(options->identity_files[options->num_identity_files++],
|
||||||
|
len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
|
||||||
|
|
||||||
|
len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
|
||||||
|
options->identity_files[options->num_identity_files] =
|
||||||
|
xmalloc(len);
|
||||||
|
snprintf(options->identity_files[options->num_identity_files++],
|
||||||
|
len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (options->escape_char == -1)
|
if (options->escape_char == -1)
|
||||||
options->escape_char = '~';
|
options->escape_char = '~';
|
||||||
if (options->system_hostfile == NULL)
|
if (options->system_hostfile == NULL)
|
||||||
options->system_hostfile = SSH_SYSTEM_HOSTFILE;
|
options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
|
||||||
if (options->user_hostfile == NULL)
|
if (options->user_hostfile == NULL)
|
||||||
options->user_hostfile = SSH_USER_HOSTFILE;
|
options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
|
||||||
if (options->system_hostfile2 == NULL)
|
if (options->system_hostfile2 == NULL)
|
||||||
options->system_hostfile2 = SSH_SYSTEM_HOSTFILE2;
|
options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
|
||||||
if (options->user_hostfile2 == NULL)
|
if (options->user_hostfile2 == NULL)
|
||||||
options->user_hostfile2 = SSH_USER_HOSTFILE2;
|
options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
|
||||||
if (options->log_level == (LogLevel) - 1)
|
if (options->log_level == (LogLevel) - 1)
|
||||||
options->log_level = SYSLOG_LEVEL_INFO;
|
options->log_level = SYSLOG_LEVEL_INFO;
|
||||||
/* options->proxy_command should not be set by default */
|
/* options->proxy_command should not be set by default */
|
||||||
/* options->user will be set in the main program if appropriate */
|
/* options->user will be set in the main program if appropriate */
|
||||||
/* options->hostname will be set in the main program if appropriate */
|
/* options->hostname will be set in the main program if appropriate */
|
||||||
|
/* options->host_key_alias should not be set by default */
|
||||||
|
/* options->preferred_authentications will be set in ssh */
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,14 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: readconf.h,v 1.22 2000/10/11 20:14:39 markus Exp $"); */
|
/* RCSID("$OpenBSD: readconf.h,v 1.30 2001/04/17 10:53:25 markus Exp $"); */
|
||||||
/* $FreeBSD$ */
|
/* RCSID("$FreeBSD$"); */
|
||||||
|
|
||||||
#ifndef READCONF_H
|
#ifndef READCONF_H
|
||||||
#define READCONF_H
|
#define READCONF_H
|
||||||
|
|
||||||
|
#include "key.h"
|
||||||
|
|
||||||
/* Data structure for representing a forwarding request. */
|
/* Data structure for representing a forwarding request. */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -36,10 +38,13 @@ typedef struct {
|
|||||||
int rhosts_rsa_authentication; /* Try rhosts with RSA
|
int rhosts_rsa_authentication; /* Try rhosts with RSA
|
||||||
* authentication. */
|
* authentication. */
|
||||||
int rsa_authentication; /* Try RSA authentication. */
|
int rsa_authentication; /* Try RSA authentication. */
|
||||||
int dsa_authentication; /* Try DSA authentication. */
|
int pubkey_authentication; /* Try ssh2 pubkey authentication. */
|
||||||
int skey_authentication; /* Try S/Key or TIS authentication. */
|
int hostbased_authentication; /* ssh2's rhosts_rsa */
|
||||||
|
int challenge_reponse_authentication;
|
||||||
|
/* Try S/Key or TIS, authentication. */
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
int kerberos_authentication; /* Try Kerberos authentication. */
|
int kerberos_authentication; /* Try Kerberos
|
||||||
|
* authentication. */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
@ -72,8 +77,11 @@ typedef struct {
|
|||||||
* prompts. */
|
* prompts. */
|
||||||
int cipher; /* Cipher to use. */
|
int cipher; /* Cipher to use. */
|
||||||
char *ciphers; /* SSH2 ciphers in order of preference. */
|
char *ciphers; /* SSH2 ciphers in order of preference. */
|
||||||
|
char *macs; /* SSH2 macs in order of preference. */
|
||||||
|
char *hostkeyalgorithms; /* SSH2 server key types in order of preference. */
|
||||||
int protocol; /* Protocol in order of preference. */
|
int protocol; /* Protocol in order of preference. */
|
||||||
char *hostname; /* Real host to connect. */
|
char *hostname; /* Real host to connect. */
|
||||||
|
char *host_key_alias; /* hostname alias for .ssh/known_hosts */
|
||||||
char *proxy_command; /* Proxy command for connecting the host. */
|
char *proxy_command; /* Proxy command for connecting the host. */
|
||||||
char *user; /* User to log in as. */
|
char *user; /* User to log in as. */
|
||||||
int escape_char; /* Escape character; -2 = none */
|
int escape_char; /* Escape character; -2 = none */
|
||||||
@ -82,11 +90,11 @@ typedef struct {
|
|||||||
char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
|
char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
|
||||||
char *system_hostfile2;
|
char *system_hostfile2;
|
||||||
char *user_hostfile2;
|
char *user_hostfile2;
|
||||||
|
char *preferred_authentications;
|
||||||
|
|
||||||
int num_identity_files; /* Number of files for RSA identities. */
|
int num_identity_files; /* Number of files for RSA/DSA identities. */
|
||||||
int num_identity_files2; /* DSA identities. */
|
|
||||||
char *identity_files[SSH_MAX_IDENTITY_FILES];
|
char *identity_files[SSH_MAX_IDENTITY_FILES];
|
||||||
char *identity_files2[SSH_MAX_IDENTITY_FILES];
|
Key *identity_keys[SSH_MAX_IDENTITY_FILES];
|
||||||
|
|
||||||
/* Local TCP/IP forward requests. */
|
/* Local TCP/IP forward requests. */
|
||||||
int num_local_forwards;
|
int num_local_forwards;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
* software must be clearly marked as such, and if the derived work is
|
* software must be clearly marked as such, and if the derived work is
|
||||||
* incompatible with the protocol description in the RFC file, it must be
|
* incompatible with the protocol description in the RFC file, it must be
|
||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Copyright (c) 1999 Niels Provos. All rights reserved.
|
* Copyright (c) 1999 Niels Provos. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -60,83 +60,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: rsa.c,v 1.16 2000/09/07 20:27:53 deraadt Exp $");
|
RCSID("$OpenBSD: rsa.c,v 1.22 2001/03/26 23:23:23 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "ssh.h"
|
#include "log.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
int rsa_verbose = 1;
|
|
||||||
|
|
||||||
int
|
|
||||||
rsa_alive()
|
|
||||||
{
|
|
||||||
RSA *key;
|
|
||||||
|
|
||||||
key = RSA_generate_key(32, 3, NULL, NULL);
|
|
||||||
if (key == NULL)
|
|
||||||
return (0);
|
|
||||||
RSA_free(key);
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generates RSA public and private keys. This initializes the data
|
|
||||||
* structures; they should be freed with rsa_clear_private_key and
|
|
||||||
* rsa_clear_public_key.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits)
|
|
||||||
{
|
|
||||||
RSA *key;
|
|
||||||
|
|
||||||
if (rsa_verbose) {
|
|
||||||
printf("Generating RSA keys: ");
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
key = RSA_generate_key(bits, 35, NULL, NULL);
|
|
||||||
if (key == NULL)
|
|
||||||
fatal("rsa_generate_key: key generation failed.");
|
|
||||||
|
|
||||||
/* Copy public key parameters */
|
|
||||||
pub->n = BN_new();
|
|
||||||
BN_copy(pub->n, key->n);
|
|
||||||
pub->e = BN_new();
|
|
||||||
BN_copy(pub->e, key->e);
|
|
||||||
|
|
||||||
/* Copy private key parameters */
|
|
||||||
prv->n = BN_new();
|
|
||||||
BN_copy(prv->n, key->n);
|
|
||||||
prv->e = BN_new();
|
|
||||||
BN_copy(prv->e, key->e);
|
|
||||||
prv->d = BN_new();
|
|
||||||
BN_copy(prv->d, key->d);
|
|
||||||
prv->p = BN_new();
|
|
||||||
BN_copy(prv->p, key->p);
|
|
||||||
prv->q = BN_new();
|
|
||||||
BN_copy(prv->q, key->q);
|
|
||||||
|
|
||||||
prv->dmp1 = BN_new();
|
|
||||||
BN_copy(prv->dmp1, key->dmp1);
|
|
||||||
|
|
||||||
prv->dmq1 = BN_new();
|
|
||||||
BN_copy(prv->dmq1, key->dmq1);
|
|
||||||
|
|
||||||
prv->iqmp = BN_new();
|
|
||||||
BN_copy(prv->iqmp, key->iqmp);
|
|
||||||
|
|
||||||
RSA_free(key);
|
|
||||||
|
|
||||||
if (rsa_verbose)
|
|
||||||
printf("Key generation complete.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||||
{
|
{
|
||||||
unsigned char *inbuf, *outbuf;
|
u_char *inbuf, *outbuf;
|
||||||
int len, ilen, olen;
|
int len, ilen, olen;
|
||||||
|
|
||||||
if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
|
if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
|
||||||
@ -151,7 +85,7 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
|||||||
|
|
||||||
if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
|
if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
|
||||||
RSA_PKCS1_PADDING)) <= 0)
|
RSA_PKCS1_PADDING)) <= 0)
|
||||||
fatal("rsa_public_encrypt() failed.");
|
fatal("rsa_public_encrypt() failed");
|
||||||
|
|
||||||
BN_bin2bn(outbuf, len, out);
|
BN_bin2bn(outbuf, len, out);
|
||||||
|
|
||||||
@ -164,7 +98,7 @@ rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
|||||||
int
|
int
|
||||||
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
||||||
{
|
{
|
||||||
unsigned char *inbuf, *outbuf;
|
u_char *inbuf, *outbuf;
|
||||||
int len, ilen, olen;
|
int len, ilen, olen;
|
||||||
|
|
||||||
olen = BN_num_bytes(key->n);
|
olen = BN_num_bytes(key->n);
|
||||||
@ -187,10 +121,22 @@ rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set whether to output verbose messages during key generation. */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rsa_set_verbose(int verbose)
|
generate_additional_parameters(RSA *rsa)
|
||||||
{
|
{
|
||||||
rsa_verbose = verbose;
|
BIGNUM *aux;
|
||||||
|
BN_CTX *ctx;
|
||||||
|
/* Generate additional parameters */
|
||||||
|
aux = BN_new();
|
||||||
|
ctx = BN_CTX_new();
|
||||||
|
|
||||||
|
BN_sub(aux, rsa->q, BN_value_one());
|
||||||
|
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
|
||||||
|
|
||||||
|
BN_sub(aux, rsa->p, BN_value_one());
|
||||||
|
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
|
||||||
|
|
||||||
|
BN_clear_free(aux);
|
||||||
|
BN_CTX_free(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: rsa.h,v 1.8 2000/09/07 20:27:53 deraadt Exp $"); */
|
/* RCSID("$OpenBSD: rsa.h,v 1.11 2001/03/26 23:23:24 markus Exp $"); */
|
||||||
/* $FreeBSD$ */
|
/* RCSID("$FreeBSD$"); */
|
||||||
|
|
||||||
#ifndef RSA_H
|
#ifndef RSA_H
|
||||||
#define RSA_H
|
#define RSA_H
|
||||||
@ -20,18 +20,9 @@
|
|||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
/* Calls SSL RSA_generate_key, only copies to prv and pub */
|
|
||||||
void rsa_generate_key(RSA * prv, RSA * pub, unsigned int bits);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indicates whether the rsa module is permitted to show messages on the
|
|
||||||
* terminal.
|
|
||||||
*/
|
|
||||||
void rsa_set_verbose __P((int verbose));
|
|
||||||
|
|
||||||
int rsa_alive __P((void));
|
|
||||||
|
|
||||||
void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
|
void rsa_public_encrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
|
||||||
int rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
|
int rsa_private_decrypt __P((BIGNUM * out, BIGNUM * in, RSA * prv));
|
||||||
|
|
||||||
|
void generate_additional_parameters __P((RSA *rsa));
|
||||||
|
|
||||||
#endif /* RSA_H */
|
#endif /* RSA_H */
|
||||||
|
@ -10,16 +10,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: servconf.c,v 1.53 2000/10/14 12:12:09 markus Exp $");
|
RCSID("$OpenBSD: servconf.c,v 1.78 2001/04/15 21:28:35 stevesk Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
|
#ifdef KRB4
|
||||||
|
#include <krb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef AFS
|
||||||
|
#include <kafs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
#include "log.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "tildexpand.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "cipher.h"
|
||||||
|
#include "kex.h"
|
||||||
|
#include "mac.h"
|
||||||
|
|
||||||
/* add listen address */
|
void add_listen_addr(ServerOptions *options, char *addr, u_short port);
|
||||||
void add_listen_addr(ServerOptions *options, char *addr);
|
void add_one_listen_addr(ServerOptions *options, char *addr, u_short port);
|
||||||
|
|
||||||
|
/* AF_UNSPEC or AF_INET or AF_INET6 */
|
||||||
|
extern int IPv4or6;
|
||||||
|
|
||||||
/* Initializes the server options to their default values. */
|
/* Initializes the server options to their default values. */
|
||||||
|
|
||||||
@ -30,16 +47,16 @@ initialize_server_options(ServerOptions *options)
|
|||||||
options->num_ports = 0;
|
options->num_ports = 0;
|
||||||
options->ports_from_cmdline = 0;
|
options->ports_from_cmdline = 0;
|
||||||
options->listen_addrs = NULL;
|
options->listen_addrs = NULL;
|
||||||
options->host_key_file = NULL;
|
options->num_host_key_files = 0;
|
||||||
options->host_dsa_key_file = NULL;
|
|
||||||
options->pid_file = NULL;
|
options->pid_file = NULL;
|
||||||
options->server_key_bits = -1;
|
options->server_key_bits = -1;
|
||||||
options->login_grace_time = -1;
|
options->login_grace_time = -1;
|
||||||
options->key_regeneration_time = -1;
|
options->key_regeneration_time = -1;
|
||||||
options->permit_root_login = -1;
|
options->permit_root_login = PERMIT_NOT_SET;
|
||||||
options->ignore_rhosts = -1;
|
options->ignore_rhosts = -1;
|
||||||
options->ignore_user_known_hosts = -1;
|
options->ignore_user_known_hosts = -1;
|
||||||
options->print_motd = -1;
|
options->print_motd = -1;
|
||||||
|
options->print_lastlog = -1;
|
||||||
options->check_mail = -1;
|
options->check_mail = -1;
|
||||||
options->x11_forwarding = -1;
|
options->x11_forwarding = -1;
|
||||||
options->x11_display_offset = -1;
|
options->x11_display_offset = -1;
|
||||||
@ -50,8 +67,10 @@ initialize_server_options(ServerOptions *options)
|
|||||||
options->log_level = (LogLevel) - 1;
|
options->log_level = (LogLevel) - 1;
|
||||||
options->rhosts_authentication = -1;
|
options->rhosts_authentication = -1;
|
||||||
options->rhosts_rsa_authentication = -1;
|
options->rhosts_rsa_authentication = -1;
|
||||||
|
options->hostbased_authentication = -1;
|
||||||
|
options->hostbased_uses_name_from_packet_only = -1;
|
||||||
options->rsa_authentication = -1;
|
options->rsa_authentication = -1;
|
||||||
options->dsa_authentication = -1;
|
options->pubkey_authentication = -1;
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
options->kerberos_authentication = -1;
|
options->kerberos_authentication = -1;
|
||||||
#endif
|
#endif
|
||||||
@ -68,9 +87,7 @@ initialize_server_options(ServerOptions *options)
|
|||||||
#endif
|
#endif
|
||||||
options->password_authentication = -1;
|
options->password_authentication = -1;
|
||||||
options->kbd_interactive_authentication = -1;
|
options->kbd_interactive_authentication = -1;
|
||||||
#ifdef SKEY
|
options->challenge_reponse_authentication = -1;
|
||||||
options->skey_authentication = -1;
|
|
||||||
#endif
|
|
||||||
options->permit_empty_passwd = -1;
|
options->permit_empty_passwd = -1;
|
||||||
options->use_login = -1;
|
options->use_login = -1;
|
||||||
options->allow_tcp_forwarding = -1;
|
options->allow_tcp_forwarding = -1;
|
||||||
@ -79,6 +96,7 @@ initialize_server_options(ServerOptions *options)
|
|||||||
options->num_allow_groups = 0;
|
options->num_allow_groups = 0;
|
||||||
options->num_deny_groups = 0;
|
options->num_deny_groups = 0;
|
||||||
options->ciphers = NULL;
|
options->ciphers = NULL;
|
||||||
|
options->macs = NULL;
|
||||||
options->protocol = SSH_PROTO_UNKNOWN;
|
options->protocol = SSH_PROTO_UNKNOWN;
|
||||||
options->gateway_ports = -1;
|
options->gateway_ports = -1;
|
||||||
options->connections_per_period = 0;
|
options->connections_per_period = 0;
|
||||||
@ -87,29 +105,38 @@ initialize_server_options(ServerOptions *options)
|
|||||||
options->max_startups_begin = -1;
|
options->max_startups_begin = -1;
|
||||||
options->max_startups_rate = -1;
|
options->max_startups_rate = -1;
|
||||||
options->max_startups = -1;
|
options->max_startups = -1;
|
||||||
|
options->banner = NULL;
|
||||||
|
options->reverse_mapping_check = -1;
|
||||||
|
options->client_alive_interval = -1;
|
||||||
|
options->client_alive_count_max = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fill_default_server_options(ServerOptions *options)
|
fill_default_server_options(ServerOptions *options)
|
||||||
{
|
{
|
||||||
|
if (options->protocol == SSH_PROTO_UNKNOWN)
|
||||||
|
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
||||||
|
if (options->num_host_key_files == 0) {
|
||||||
|
/* fill default hostkeys for protocols */
|
||||||
|
if (options->protocol & SSH_PROTO_1)
|
||||||
|
options->host_key_files[options->num_host_key_files++] = _PATH_HOST_KEY_FILE;
|
||||||
|
if (options->protocol & SSH_PROTO_2)
|
||||||
|
options->host_key_files[options->num_host_key_files++] = _PATH_HOST_DSA_KEY_FILE;
|
||||||
|
}
|
||||||
if (options->num_ports == 0)
|
if (options->num_ports == 0)
|
||||||
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
|
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
|
||||||
if (options->listen_addrs == NULL)
|
if (options->listen_addrs == NULL)
|
||||||
add_listen_addr(options, NULL);
|
add_listen_addr(options, NULL, 0);
|
||||||
if (options->host_key_file == NULL)
|
|
||||||
options->host_key_file = HOST_KEY_FILE;
|
|
||||||
if (options->host_dsa_key_file == NULL)
|
|
||||||
options->host_dsa_key_file = HOST_DSA_KEY_FILE;
|
|
||||||
if (options->pid_file == NULL)
|
if (options->pid_file == NULL)
|
||||||
options->pid_file = SSH_DAEMON_PID_FILE;
|
options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
|
||||||
if (options->server_key_bits == -1)
|
if (options->server_key_bits == -1)
|
||||||
options->server_key_bits = 768;
|
options->server_key_bits = 768;
|
||||||
if (options->login_grace_time == -1)
|
if (options->login_grace_time == -1)
|
||||||
options->login_grace_time = 120;
|
options->login_grace_time = 120;
|
||||||
if (options->key_regeneration_time == -1)
|
if (options->key_regeneration_time == -1)
|
||||||
options->key_regeneration_time = 3600;
|
options->key_regeneration_time = 3600;
|
||||||
if (options->permit_root_login == -1)
|
if (options->permit_root_login == PERMIT_NOT_SET)
|
||||||
options->permit_root_login = 0; /* no */
|
options->permit_root_login = PERMIT_NO;
|
||||||
if (options->ignore_rhosts == -1)
|
if (options->ignore_rhosts == -1)
|
||||||
options->ignore_rhosts = 1;
|
options->ignore_rhosts = 1;
|
||||||
if (options->ignore_user_known_hosts == -1)
|
if (options->ignore_user_known_hosts == -1)
|
||||||
@ -118,6 +145,8 @@ fill_default_server_options(ServerOptions *options)
|
|||||||
options->check_mail = 1;
|
options->check_mail = 1;
|
||||||
if (options->print_motd == -1)
|
if (options->print_motd == -1)
|
||||||
options->print_motd = 1;
|
options->print_motd = 1;
|
||||||
|
if (options->print_lastlog == -1)
|
||||||
|
options->print_lastlog = 1;
|
||||||
if (options->x11_forwarding == -1)
|
if (options->x11_forwarding == -1)
|
||||||
options->x11_forwarding = 1;
|
options->x11_forwarding = 1;
|
||||||
if (options->x11_display_offset == -1)
|
if (options->x11_display_offset == -1)
|
||||||
@ -138,10 +167,14 @@ fill_default_server_options(ServerOptions *options)
|
|||||||
options->rhosts_authentication = 0;
|
options->rhosts_authentication = 0;
|
||||||
if (options->rhosts_rsa_authentication == -1)
|
if (options->rhosts_rsa_authentication == -1)
|
||||||
options->rhosts_rsa_authentication = 0;
|
options->rhosts_rsa_authentication = 0;
|
||||||
|
if (options->hostbased_authentication == -1)
|
||||||
|
options->hostbased_authentication = 0;
|
||||||
|
if (options->hostbased_uses_name_from_packet_only == -1)
|
||||||
|
options->hostbased_uses_name_from_packet_only = 0;
|
||||||
if (options->rsa_authentication == -1)
|
if (options->rsa_authentication == -1)
|
||||||
options->rsa_authentication = 1;
|
options->rsa_authentication = 1;
|
||||||
if (options->dsa_authentication == -1)
|
if (options->pubkey_authentication == -1)
|
||||||
options->dsa_authentication = 1;
|
options->pubkey_authentication = 1;
|
||||||
#if defined(KRB4) && defined(KRB5)
|
#if defined(KRB4) && defined(KRB5)
|
||||||
if (options->kerberos_authentication == -1)
|
if (options->kerberos_authentication == -1)
|
||||||
options->kerberos_authentication =
|
options->kerberos_authentication =
|
||||||
@ -173,18 +206,14 @@ fill_default_server_options(ServerOptions *options)
|
|||||||
options->password_authentication = 1;
|
options->password_authentication = 1;
|
||||||
if (options->kbd_interactive_authentication == -1)
|
if (options->kbd_interactive_authentication == -1)
|
||||||
options->kbd_interactive_authentication = 0;
|
options->kbd_interactive_authentication = 0;
|
||||||
#ifdef SKEY
|
if (options->challenge_reponse_authentication == -1)
|
||||||
if (options->skey_authentication == -1)
|
options->challenge_reponse_authentication = 1;
|
||||||
options->skey_authentication = 1;
|
|
||||||
#endif
|
|
||||||
if (options->permit_empty_passwd == -1)
|
if (options->permit_empty_passwd == -1)
|
||||||
options->permit_empty_passwd = 0;
|
options->permit_empty_passwd = 0;
|
||||||
if (options->use_login == -1)
|
if (options->use_login == -1)
|
||||||
options->use_login = 0;
|
options->use_login = 0;
|
||||||
if (options->allow_tcp_forwarding == -1)
|
if (options->allow_tcp_forwarding == -1)
|
||||||
options->allow_tcp_forwarding = 1;
|
options->allow_tcp_forwarding = 1;
|
||||||
if (options->protocol == SSH_PROTO_UNKNOWN)
|
|
||||||
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
|
|
||||||
if (options->gateway_ports == -1)
|
if (options->gateway_ports == -1)
|
||||||
options->gateway_ports = 0;
|
options->gateway_ports = 0;
|
||||||
if (options->max_startups == -1)
|
if (options->max_startups == -1)
|
||||||
@ -193,6 +222,12 @@ fill_default_server_options(ServerOptions *options)
|
|||||||
options->max_startups_rate = 100; /* 100% */
|
options->max_startups_rate = 100; /* 100% */
|
||||||
if (options->max_startups_begin == -1)
|
if (options->max_startups_begin == -1)
|
||||||
options->max_startups_begin = options->max_startups;
|
options->max_startups_begin = options->max_startups;
|
||||||
|
if (options->reverse_mapping_check == -1)
|
||||||
|
options->reverse_mapping_check = 0;
|
||||||
|
if (options->client_alive_interval == -1)
|
||||||
|
options->client_alive_interval = 0;
|
||||||
|
if (options->client_alive_count_max == -1)
|
||||||
|
options->client_alive_count_max = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Keyword tokens. */
|
/* Keyword tokens. */
|
||||||
@ -213,17 +248,18 @@ typedef enum {
|
|||||||
#ifdef AFS
|
#ifdef AFS
|
||||||
sKrb4TgtPassing, sAFSTokenPassing,
|
sKrb4TgtPassing, sAFSTokenPassing,
|
||||||
#endif
|
#endif
|
||||||
#ifdef SKEY
|
sChallengeResponseAuthentication,
|
||||||
sSkeyAuthentication,
|
|
||||||
#endif
|
|
||||||
sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
|
sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
|
||||||
sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
|
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
|
||||||
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
|
sX11Forwarding, sX11DisplayOffset,
|
||||||
|
sStrictModes, sEmptyPasswd, sKeepAlives, sCheckMail,
|
||||||
sUseLogin, sAllowTcpForwarding,
|
sUseLogin, sAllowTcpForwarding,
|
||||||
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
|
sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
|
||||||
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
|
sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
|
||||||
sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod, sXAuthLocation,
|
sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
|
||||||
sSubsystem, sMaxStartups, sVersionAddendum
|
sBanner, sReverseMappingCheck, sHostbasedAuthentication,
|
||||||
|
sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
|
||||||
|
sClientAliveCountMax, sVersionAddendum, sConnectionsPerPeriod
|
||||||
} ServerOpCodes;
|
} ServerOpCodes;
|
||||||
|
|
||||||
/* Textual representation of the tokens. */
|
/* Textual representation of the tokens. */
|
||||||
@ -233,8 +269,8 @@ static struct {
|
|||||||
} keywords[] = {
|
} keywords[] = {
|
||||||
{ "port", sPort },
|
{ "port", sPort },
|
||||||
{ "hostkey", sHostKeyFile },
|
{ "hostkey", sHostKeyFile },
|
||||||
{ "hostdsakey", sHostDSAKeyFile },
|
{ "hostdsakey", sHostKeyFile }, /* alias */
|
||||||
{ "pidfile", sPidFile },
|
{ "pidfile", sPidFile },
|
||||||
{ "serverkeybits", sServerKeyBits },
|
{ "serverkeybits", sServerKeyBits },
|
||||||
{ "logingracetime", sLoginGraceTime },
|
{ "logingracetime", sLoginGraceTime },
|
||||||
{ "keyregenerationinterval", sKeyRegenerationTime },
|
{ "keyregenerationinterval", sKeyRegenerationTime },
|
||||||
@ -243,8 +279,11 @@ static struct {
|
|||||||
{ "loglevel", sLogLevel },
|
{ "loglevel", sLogLevel },
|
||||||
{ "rhostsauthentication", sRhostsAuthentication },
|
{ "rhostsauthentication", sRhostsAuthentication },
|
||||||
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
|
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
|
||||||
|
{ "hostbasedauthentication", sHostbasedAuthentication },
|
||||||
|
{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
|
||||||
|
{ "pubkeyauthentication", sPubkeyAuthentication },
|
||||||
|
{ "dsaauthentication", sPubkeyAuthentication }, /* alias */
|
||||||
{ "rsaauthentication", sRSAAuthentication },
|
{ "rsaauthentication", sRSAAuthentication },
|
||||||
{ "dsaauthentication", sDSAAuthentication },
|
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
{ "kerberosauthentication", sKerberosAuthentication },
|
{ "kerberosauthentication", sKerberosAuthentication },
|
||||||
#endif
|
#endif
|
||||||
@ -261,12 +300,12 @@ static struct {
|
|||||||
#endif
|
#endif
|
||||||
{ "passwordauthentication", sPasswordAuthentication },
|
{ "passwordauthentication", sPasswordAuthentication },
|
||||||
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
|
{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
|
||||||
#ifdef SKEY
|
{ "challengeresponseauthentication", sChallengeResponseAuthentication },
|
||||||
{ "skeyauthentication", sSkeyAuthentication },
|
{ "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
|
||||||
#endif
|
|
||||||
{ "checkmail", sCheckMail },
|
{ "checkmail", sCheckMail },
|
||||||
{ "listenaddress", sListenAddress },
|
{ "listenaddress", sListenAddress },
|
||||||
{ "printmotd", sPrintMotd },
|
{ "printmotd", sPrintMotd },
|
||||||
|
{ "printlastlog", sPrintLastLog },
|
||||||
{ "ignorerhosts", sIgnoreRhosts },
|
{ "ignorerhosts", sIgnoreRhosts },
|
||||||
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
|
{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
|
||||||
{ "x11forwarding", sX11Forwarding },
|
{ "x11forwarding", sX11Forwarding },
|
||||||
@ -275,7 +314,6 @@ static struct {
|
|||||||
{ "strictmodes", sStrictModes },
|
{ "strictmodes", sStrictModes },
|
||||||
{ "permitemptypasswords", sEmptyPasswd },
|
{ "permitemptypasswords", sEmptyPasswd },
|
||||||
{ "uselogin", sUseLogin },
|
{ "uselogin", sUseLogin },
|
||||||
{ "randomseed", sRandomSeedFile },
|
|
||||||
{ "keepalive", sKeepAlives },
|
{ "keepalive", sKeepAlives },
|
||||||
{ "allowtcpforwarding", sAllowTcpForwarding },
|
{ "allowtcpforwarding", sAllowTcpForwarding },
|
||||||
{ "allowusers", sAllowUsers },
|
{ "allowusers", sAllowUsers },
|
||||||
@ -283,64 +321,73 @@ static struct {
|
|||||||
{ "allowgroups", sAllowGroups },
|
{ "allowgroups", sAllowGroups },
|
||||||
{ "denygroups", sDenyGroups },
|
{ "denygroups", sDenyGroups },
|
||||||
{ "ciphers", sCiphers },
|
{ "ciphers", sCiphers },
|
||||||
|
{ "macs", sMacs },
|
||||||
{ "protocol", sProtocol },
|
{ "protocol", sProtocol },
|
||||||
{ "gatewayports", sGatewayPorts },
|
{ "gatewayports", sGatewayPorts },
|
||||||
{ "connectionsperperiod", sConnectionsPerPeriod },
|
{ "connectionsperperiod", sConnectionsPerPeriod },
|
||||||
{ "subsystem", sSubsystem },
|
{ "subsystem", sSubsystem },
|
||||||
{ "maxstartups", sMaxStartups },
|
{ "maxstartups", sMaxStartups },
|
||||||
{ "versionaddendum", sVersionAddendum },
|
{ "versionaddendum", sVersionAddendum },
|
||||||
|
{ "banner", sBanner },
|
||||||
|
{ "reversemappingcheck", sReverseMappingCheck },
|
||||||
|
{ "clientaliveinterval", sClientAliveInterval },
|
||||||
|
{ "clientalivecountmax", sClientAliveCountMax },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the number of the token pointed to by cp of length len. Never
|
* Returns the number of the token pointed to by cp or sBadOption.
|
||||||
* returns if the token is not known.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static ServerOpCodes
|
static ServerOpCodes
|
||||||
parse_token(const char *cp, const char *filename,
|
parse_token(const char *cp, const char *filename,
|
||||||
int linenum)
|
int linenum)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; keywords[i].name; i++)
|
for (i = 0; keywords[i].name; i++)
|
||||||
if (strcasecmp(cp, keywords[i].name) == 0)
|
if (strcasecmp(cp, keywords[i].name) == 0)
|
||||||
return keywords[i].opcode;
|
return keywords[i].opcode;
|
||||||
|
|
||||||
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
|
error("%s: line %d: Bad configuration option: %s",
|
||||||
filename, linenum, cp);
|
filename, linenum, cp);
|
||||||
return sBadOption;
|
return sBadOption;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* add listen address
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
add_listen_addr(ServerOptions *options, char *addr)
|
add_listen_addr(ServerOptions *options, char *addr, u_short port)
|
||||||
{
|
{
|
||||||
extern int IPv4or6;
|
|
||||||
struct addrinfo hints, *ai, *aitop;
|
|
||||||
char strport[NI_MAXSERV];
|
|
||||||
int gaierr;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (options->num_ports == 0)
|
if (options->num_ports == 0)
|
||||||
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
|
options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
|
||||||
for (i = 0; i < options->num_ports; i++) {
|
if (port == 0)
|
||||||
memset(&hints, 0, sizeof(hints));
|
for (i = 0; i < options->num_ports; i++)
|
||||||
hints.ai_family = IPv4or6;
|
add_one_listen_addr(options, addr, options->ports[i]);
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
else
|
||||||
hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
|
add_one_listen_addr(options, addr, port);
|
||||||
snprintf(strport, sizeof strport, "%d", options->ports[i]);
|
}
|
||||||
if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
|
|
||||||
fatal("bad addr or host: %s (%s)\n",
|
void
|
||||||
addr ? addr : "<NULL>",
|
add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
|
||||||
gai_strerror(gaierr));
|
{
|
||||||
for (ai = aitop; ai->ai_next; ai = ai->ai_next)
|
struct addrinfo hints, *ai, *aitop;
|
||||||
;
|
char strport[NI_MAXSERV];
|
||||||
ai->ai_next = options->listen_addrs;
|
int gaierr;
|
||||||
options->listen_addrs = aitop;
|
|
||||||
}
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = IPv4or6;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
|
||||||
|
snprintf(strport, sizeof strport, "%d", port);
|
||||||
|
if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
|
||||||
|
fatal("bad addr or host: %s (%s)",
|
||||||
|
addr ? addr : "<NULL>",
|
||||||
|
gai_strerror(gaierr));
|
||||||
|
for (ai = aitop; ai->ai_next; ai = ai->ai_next)
|
||||||
|
;
|
||||||
|
ai->ai_next = options->listen_addrs;
|
||||||
|
options->listen_addrs = aitop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reads the server configuration file. */
|
/* Reads the server configuration file. */
|
||||||
@ -350,7 +397,7 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char line[1024];
|
char line[1024];
|
||||||
char *cp, **charptr, *arg;
|
char *cp, **charptr, *arg, *p;
|
||||||
int linenum, *intptr, value;
|
int linenum, *intptr, value;
|
||||||
int bad_options = 0;
|
int bad_options = 0;
|
||||||
ServerOpCodes opcode;
|
ServerOpCodes opcode;
|
||||||
@ -369,8 +416,10 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
/* Ignore leading whitespace */
|
/* Ignore leading whitespace */
|
||||||
if (*arg == '\0')
|
if (*arg == '\0')
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
if (!*arg || *arg == '#')
|
if (!arg || !*arg || *arg == '#')
|
||||||
continue;
|
continue;
|
||||||
|
intptr = NULL;
|
||||||
|
charptr = NULL;
|
||||||
opcode = parse_token(arg, filename, linenum);
|
opcode = parse_token(arg, filename, linenum);
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case sBadOption:
|
case sBadOption:
|
||||||
@ -384,24 +433,25 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
fatal("%s line %d: ports must be specified before "
|
fatal("%s line %d: ports must be specified before "
|
||||||
"ListenAdress.\n", filename, linenum);
|
"ListenAdress.\n", filename, linenum);
|
||||||
if (options->num_ports >= MAX_PORTS)
|
if (options->num_ports >= MAX_PORTS)
|
||||||
fatal("%s line %d: too many ports.\n",
|
fatal("%s line %d: too many ports.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0')
|
||||||
fatal("%s line %d: missing port number.\n",
|
fatal("%s line %d: missing port number.",
|
||||||
|
filename, linenum);
|
||||||
|
options->ports[options->num_ports++] = a2port(arg);
|
||||||
|
if (options->ports[options->num_ports-1] == 0)
|
||||||
|
fatal("%s line %d: Badly formatted port number.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->ports[options->num_ports++] = atoi(arg);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sServerKeyBits:
|
case sServerKeyBits:
|
||||||
intptr = &options->server_key_bits;
|
intptr = &options->server_key_bits;
|
||||||
parse_int:
|
parse_int:
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
if (!arg || *arg == '\0') {
|
if (!arg || *arg == '\0')
|
||||||
fprintf(stderr, "%s line %d: missing integer value.\n",
|
fatal("%s line %d: missing integer value.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
value = atoi(arg);
|
value = atoi(arg);
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
fprintf(stderr, "%s line %d: invalid integer value.\n",
|
fprintf(stderr, "%s line %d: invalid integer value.\n",
|
||||||
@ -422,56 +472,84 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
|
|
||||||
case sListenAddress:
|
case sListenAddress:
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
if (!arg || *arg == '\0')
|
if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
|
||||||
fatal("%s line %d: missing inet addr.\n",
|
fatal("%s line %d: missing inet addr.",
|
||||||
|
filename, linenum);
|
||||||
|
if (*arg == '[') {
|
||||||
|
if ((p = strchr(arg, ']')) == NULL)
|
||||||
|
fatal("%s line %d: bad ipv6 inet addr usage.",
|
||||||
|
filename, linenum);
|
||||||
|
arg++;
|
||||||
|
memmove(p, p+1, strlen(p+1)+1);
|
||||||
|
} else if (((p = strchr(arg, ':')) == NULL) ||
|
||||||
|
(strchr(p+1, ':') != NULL)) {
|
||||||
|
add_listen_addr(options, arg, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*p == ':') {
|
||||||
|
u_short port;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
if (*p == '\0')
|
||||||
|
fatal("%s line %d: bad inet addr:port usage.",
|
||||||
|
filename, linenum);
|
||||||
|
else {
|
||||||
|
*(p-1) = '\0';
|
||||||
|
if ((port = a2port(p)) == 0)
|
||||||
|
fatal("%s line %d: bad port number.",
|
||||||
|
filename, linenum);
|
||||||
|
add_listen_addr(options, arg, port);
|
||||||
|
}
|
||||||
|
} else if (*p == '\0')
|
||||||
|
add_listen_addr(options, arg, 0);
|
||||||
|
else
|
||||||
|
fatal("%s line %d: bad inet addr usage.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
add_listen_addr(options, arg);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sHostKeyFile:
|
case sHostKeyFile:
|
||||||
case sHostDSAKeyFile:
|
intptr = &options->num_host_key_files;
|
||||||
charptr = (opcode == sHostKeyFile ) ?
|
if (*intptr >= MAX_HOSTKEYS)
|
||||||
&options->host_key_file : &options->host_dsa_key_file;
|
fatal("%s line %d: too many host keys specified (max %d).",
|
||||||
|
filename, linenum, MAX_HOSTKEYS);
|
||||||
|
charptr = &options->host_key_files[*intptr];
|
||||||
parse_filename:
|
parse_filename:
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
if (!arg || *arg == '\0') {
|
if (!arg || *arg == '\0')
|
||||||
fprintf(stderr, "%s line %d: missing file name.\n",
|
fatal("%s line %d: missing file name.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
exit(1);
|
if (*charptr == NULL) {
|
||||||
}
|
|
||||||
if (*charptr == NULL)
|
|
||||||
*charptr = tilde_expand_filename(arg, getuid());
|
*charptr = tilde_expand_filename(arg, getuid());
|
||||||
|
/* increase optional counter */
|
||||||
|
if (intptr != NULL)
|
||||||
|
*intptr = *intptr + 1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case sPidFile:
|
case sPidFile:
|
||||||
charptr = &options->pid_file;
|
charptr = &options->pid_file;
|
||||||
goto parse_filename;
|
goto parse_filename;
|
||||||
|
|
||||||
case sRandomSeedFile:
|
|
||||||
fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n",
|
|
||||||
filename, linenum);
|
|
||||||
arg = strdelim(&cp);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case sPermitRootLogin:
|
case sPermitRootLogin:
|
||||||
intptr = &options->permit_root_login;
|
intptr = &options->permit_root_login;
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
if (!arg || *arg == '\0') {
|
if (!arg || *arg == '\0')
|
||||||
fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n",
|
fatal("%s line %d: missing yes/"
|
||||||
filename, linenum);
|
"without-password/forced-commands-only/no "
|
||||||
exit(1);
|
"argument.", filename, linenum);
|
||||||
}
|
value = 0; /* silence compiler */
|
||||||
if (strcmp(arg, "without-password") == 0)
|
if (strcmp(arg, "without-password") == 0)
|
||||||
value = 2;
|
value = PERMIT_NO_PASSWD;
|
||||||
|
else if (strcmp(arg, "forced-commands-only") == 0)
|
||||||
|
value = PERMIT_FORCED_ONLY;
|
||||||
else if (strcmp(arg, "yes") == 0)
|
else if (strcmp(arg, "yes") == 0)
|
||||||
value = 1;
|
value = PERMIT_YES;
|
||||||
else if (strcmp(arg, "no") == 0)
|
else if (strcmp(arg, "no") == 0)
|
||||||
value = 0;
|
value = PERMIT_NO;
|
||||||
else {
|
else
|
||||||
fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
|
fatal("%s line %d: Bad yes/"
|
||||||
filename, linenum, arg);
|
"without-password/forced-commands-only/no "
|
||||||
exit(1);
|
"argument: %s", filename, linenum, arg);
|
||||||
}
|
|
||||||
if (*intptr == -1)
|
if (*intptr == -1)
|
||||||
*intptr = value;
|
*intptr = value;
|
||||||
break;
|
break;
|
||||||
@ -480,20 +558,17 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
intptr = &options->ignore_rhosts;
|
intptr = &options->ignore_rhosts;
|
||||||
parse_flag:
|
parse_flag:
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
if (!arg || *arg == '\0') {
|
if (!arg || *arg == '\0')
|
||||||
fprintf(stderr, "%s line %d: missing yes/no argument.\n",
|
fatal("%s line %d: missing yes/no argument.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
exit(1);
|
value = 0; /* silence compiler */
|
||||||
}
|
|
||||||
if (strcmp(arg, "yes") == 0)
|
if (strcmp(arg, "yes") == 0)
|
||||||
value = 1;
|
value = 1;
|
||||||
else if (strcmp(arg, "no") == 0)
|
else if (strcmp(arg, "no") == 0)
|
||||||
value = 0;
|
value = 0;
|
||||||
else {
|
else
|
||||||
fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n",
|
fatal("%s line %d: Bad yes/no argument: %s",
|
||||||
filename, linenum, arg);
|
filename, linenum, arg);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
if (*intptr == -1)
|
if (*intptr == -1)
|
||||||
*intptr = value;
|
*intptr = value;
|
||||||
break;
|
break;
|
||||||
@ -510,12 +585,20 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
intptr = &options->rhosts_rsa_authentication;
|
intptr = &options->rhosts_rsa_authentication;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
|
case sHostbasedAuthentication:
|
||||||
|
intptr = &options->hostbased_authentication;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
|
case sHostbasedUsesNameFromPacketOnly:
|
||||||
|
intptr = &options->hostbased_uses_name_from_packet_only;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
case sRSAAuthentication:
|
case sRSAAuthentication:
|
||||||
intptr = &options->rsa_authentication;
|
intptr = &options->rsa_authentication;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
case sDSAAuthentication:
|
case sPubkeyAuthentication:
|
||||||
intptr = &options->dsa_authentication;
|
intptr = &options->pubkey_authentication;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
@ -562,16 +645,18 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
intptr = &options->check_mail;
|
intptr = &options->check_mail;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
#ifdef SKEY
|
case sChallengeResponseAuthentication:
|
||||||
case sSkeyAuthentication:
|
intptr = &options->challenge_reponse_authentication;
|
||||||
intptr = &options->skey_authentication;
|
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
#endif
|
|
||||||
|
|
||||||
case sPrintMotd:
|
case sPrintMotd:
|
||||||
intptr = &options->print_motd;
|
intptr = &options->print_motd;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
|
case sPrintLastLog:
|
||||||
|
intptr = &options->print_lastlog;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
case sX11Forwarding:
|
case sX11Forwarding:
|
||||||
intptr = &options->x11_forwarding;
|
intptr = &options->x11_forwarding;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
@ -583,7 +668,7 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
case sXAuthLocation:
|
case sXAuthLocation:
|
||||||
charptr = &options->xauth_location;
|
charptr = &options->xauth_location;
|
||||||
goto parse_filename;
|
goto parse_filename;
|
||||||
|
|
||||||
case sStrictModes:
|
case sStrictModes:
|
||||||
intptr = &options->strict_modes;
|
intptr = &options->strict_modes;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
@ -604,12 +689,16 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
intptr = &options->gateway_ports;
|
intptr = &options->gateway_ports;
|
||||||
goto parse_flag;
|
goto parse_flag;
|
||||||
|
|
||||||
|
case sReverseMappingCheck:
|
||||||
|
intptr = &options->reverse_mapping_check;
|
||||||
|
goto parse_flag;
|
||||||
|
|
||||||
case sLogFacility:
|
case sLogFacility:
|
||||||
intptr = (int *) &options->log_facility;
|
intptr = (int *) &options->log_facility;
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
value = log_facility_number(arg);
|
value = log_facility_number(arg);
|
||||||
if (value == (SyslogFacility) - 1)
|
if (value == (SyslogFacility) - 1)
|
||||||
fatal("%.200s line %d: unsupported log facility '%s'\n",
|
fatal("%.200s line %d: unsupported log facility '%s'",
|
||||||
filename, linenum, arg ? arg : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*intptr == -1)
|
if (*intptr == -1)
|
||||||
*intptr = (SyslogFacility) value;
|
*intptr = (SyslogFacility) value;
|
||||||
@ -620,7 +709,7 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
value = log_level_number(arg);
|
value = log_level_number(arg);
|
||||||
if (value == (LogLevel) - 1)
|
if (value == (LogLevel) - 1)
|
||||||
fatal("%.200s line %d: unsupported log level '%s'\n",
|
fatal("%.200s line %d: unsupported log level '%s'",
|
||||||
filename, linenum, arg ? arg : "<NONE>");
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
if (*intptr == -1)
|
if (*intptr == -1)
|
||||||
*intptr = (LogLevel) value;
|
*intptr = (LogLevel) value;
|
||||||
@ -633,7 +722,7 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
case sAllowUsers:
|
case sAllowUsers:
|
||||||
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
if (options->num_allow_users >= MAX_ALLOW_USERS)
|
if (options->num_allow_users >= MAX_ALLOW_USERS)
|
||||||
fatal("%.200s line %d: too many allow users.\n",
|
fatal("%.200s line %d: too many allow users.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->allow_users[options->num_allow_users++] = xstrdup(arg);
|
options->allow_users[options->num_allow_users++] = xstrdup(arg);
|
||||||
}
|
}
|
||||||
@ -642,7 +731,7 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
case sDenyUsers:
|
case sDenyUsers:
|
||||||
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
if (options->num_deny_users >= MAX_DENY_USERS)
|
if (options->num_deny_users >= MAX_DENY_USERS)
|
||||||
fatal("%.200s line %d: too many deny users.\n",
|
fatal(".200%s line %d: too many deny users.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->deny_users[options->num_deny_users++] = xstrdup(arg);
|
options->deny_users[options->num_deny_users++] = xstrdup(arg);
|
||||||
}
|
}
|
||||||
@ -651,7 +740,7 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
case sAllowGroups:
|
case sAllowGroups:
|
||||||
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
|
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
|
||||||
fatal("%.200s line %d: too many allow groups.\n",
|
fatal("%.200s line %d: too many allow groups.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
|
options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
|
||||||
}
|
}
|
||||||
@ -660,7 +749,7 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
case sDenyGroups:
|
case sDenyGroups:
|
||||||
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
while ((arg = strdelim(&cp)) && *arg != '\0') {
|
||||||
if (options->num_deny_groups >= MAX_DENY_GROUPS)
|
if (options->num_deny_groups >= MAX_DENY_GROUPS)
|
||||||
fatal("%.200s line %d: too many deny groups.\n",
|
fatal("%.200s line %d: too many deny groups.",
|
||||||
filename, linenum);
|
filename, linenum);
|
||||||
options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
|
options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
|
||||||
}
|
}
|
||||||
@ -677,6 +766,17 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
options->ciphers = xstrdup(arg);
|
options->ciphers = xstrdup(arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case sMacs:
|
||||||
|
arg = strdelim(&cp);
|
||||||
|
if (!arg || *arg == '\0')
|
||||||
|
fatal("%s line %d: Missing argument.", filename, linenum);
|
||||||
|
if (!mac_valid(arg))
|
||||||
|
fatal("%s line %d: Bad SSH2 mac spec '%s'.",
|
||||||
|
filename, linenum, arg ? arg : "<NONE>");
|
||||||
|
if (options->macs == NULL)
|
||||||
|
options->macs = xstrdup(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
case sProtocol:
|
case sProtocol:
|
||||||
intptr = &options->protocol;
|
intptr = &options->protocol;
|
||||||
arg = strdelim(&cp);
|
arg = strdelim(&cp);
|
||||||
@ -744,20 +844,25 @@ read_server_config(ServerOptions *options, const char *filename)
|
|||||||
while (arg != NULL && *arg != '\0');
|
while (arg != NULL && *arg != '\0');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case sBanner:
|
||||||
|
charptr = &options->banner;
|
||||||
|
goto parse_filename;
|
||||||
|
case sClientAliveInterval:
|
||||||
|
intptr = &options->client_alive_interval;
|
||||||
|
goto parse_int;
|
||||||
|
case sClientAliveCountMax:
|
||||||
|
intptr = &options->client_alive_count_max;
|
||||||
|
goto parse_int;
|
||||||
default:
|
default:
|
||||||
fatal("%.200s line %d: Missing handler for opcode %s (%d)\n",
|
fatal("%.200s line %d: Missing handler for opcode %s (%d)",
|
||||||
filename, linenum,arg, opcode);
|
filename, linenum, arg, opcode);
|
||||||
}
|
|
||||||
if ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
|
|
||||||
fprintf(stderr,
|
|
||||||
"%s line %d: garbage at end of line; \"%.200s\".\n",
|
|
||||||
filename, linenum, arg);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
|
||||||
|
fatal("%s line %d: garbage at end of line; \"%.200s\".",
|
||||||
|
filename, linenum, arg);
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
if (bad_options > 0) {
|
if (bad_options > 0)
|
||||||
fatal("%.200s: terminating, %d bad configuration options\n",
|
fatal("%.200s: terminating, %d bad configuration options",
|
||||||
filename, bad_options);
|
filename, bad_options);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: servconf.h,v 1.30 2000/10/14 12:12:09 markus Exp $"); */
|
/* RCSID("$OpenBSD: servconf.h,v 1.41 2001/04/13 22:46:53 beck Exp $"); */
|
||||||
/* $FreeBSD$ */
|
/* RCSID("$FreeBSD$"); */
|
||||||
|
|
||||||
#ifndef SERVCONF_H
|
#ifndef SERVCONF_H
|
||||||
#define SERVCONF_H
|
#define SERVCONF_H
|
||||||
@ -24,25 +24,35 @@
|
|||||||
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
|
#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */
|
||||||
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
|
#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */
|
||||||
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
|
#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */
|
||||||
|
#define MAX_HOSTKEYS 256 /* Max # hostkeys. */
|
||||||
|
|
||||||
|
/* permit_root_login */
|
||||||
|
#define PERMIT_NOT_SET -1
|
||||||
|
#define PERMIT_NO 0
|
||||||
|
#define PERMIT_FORCED_ONLY 1
|
||||||
|
#define PERMIT_NO_PASSWD 2
|
||||||
|
#define PERMIT_YES 3
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int num_ports;
|
u_int num_ports;
|
||||||
unsigned int ports_from_cmdline;
|
u_int ports_from_cmdline;
|
||||||
u_short ports[MAX_PORTS]; /* Port number to listen on. */
|
u_short ports[MAX_PORTS]; /* Port number to listen on. */
|
||||||
char *listen_addr; /* Address on which the server listens. */
|
char *listen_addr; /* Address on which the server listens. */
|
||||||
struct addrinfo *listen_addrs; /* Addresses on which the server listens. */
|
struct addrinfo *listen_addrs; /* Addresses on which the server listens. */
|
||||||
char *host_key_file; /* File containing host key. */
|
char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */
|
||||||
char *host_dsa_key_file; /* File containing dsa host key. */
|
int num_host_key_files; /* Number of files for host keys. */
|
||||||
char *pid_file; /* Where to put our pid */
|
char *pid_file; /* Where to put our pid */
|
||||||
int server_key_bits;/* Size of the server key. */
|
int server_key_bits;/* Size of the server key. */
|
||||||
int login_grace_time; /* Disconnect if no auth in this time
|
int login_grace_time; /* Disconnect if no auth in this time
|
||||||
* (sec). */
|
* (sec). */
|
||||||
int key_regeneration_time; /* Server key lifetime (seconds). */
|
int key_regeneration_time; /* Server key lifetime (seconds). */
|
||||||
int permit_root_login; /* If true, permit root login. */
|
int permit_root_login; /* PERMIT_*, see above */
|
||||||
int ignore_rhosts; /* Ignore .rhosts and .shosts. */
|
int ignore_rhosts; /* Ignore .rhosts and .shosts. */
|
||||||
int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts
|
int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts
|
||||||
* for RhostsRsaAuth */
|
* for RhostsRsaAuth */
|
||||||
int print_motd; /* If true, print /etc/motd. */
|
int print_motd; /* If true, print /etc/motd. */
|
||||||
|
int print_lastlog; /* If true, print lastlog */
|
||||||
int check_mail; /* If true, check for new mail. */
|
int check_mail; /* If true, check for new mail. */
|
||||||
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
|
int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */
|
||||||
int x11_display_offset; /* What DISPLAY number to start
|
int x11_display_offset; /* What DISPLAY number to start
|
||||||
@ -50,8 +60,9 @@ typedef struct {
|
|||||||
char *xauth_location; /* Location of xauth program */
|
char *xauth_location; /* Location of xauth program */
|
||||||
int strict_modes; /* If true, require string home dir modes. */
|
int strict_modes; /* If true, require string home dir modes. */
|
||||||
int keepalives; /* If true, set SO_KEEPALIVE. */
|
int keepalives; /* If true, set SO_KEEPALIVE. */
|
||||||
char *ciphers; /* Ciphers in order of preference. */
|
char *ciphers; /* Supported SSH2 ciphers. */
|
||||||
int protocol; /* Protocol in order of preference. */
|
char *macs; /* Supported SSH2 macs. */
|
||||||
|
int protocol; /* Supported protocol versions. */
|
||||||
int gateway_ports; /* If true, allow remote connects to forwarded ports. */
|
int gateway_ports; /* If true, allow remote connects to forwarded ports. */
|
||||||
SyslogFacility log_facility; /* Facility for system logging. */
|
SyslogFacility log_facility; /* Facility for system logging. */
|
||||||
LogLevel log_level; /* Level for system logging. */
|
LogLevel log_level; /* Level for system logging. */
|
||||||
@ -59,11 +70,13 @@ typedef struct {
|
|||||||
* authentication. */
|
* authentication. */
|
||||||
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
|
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
|
||||||
* authentication. */
|
* authentication. */
|
||||||
|
int hostbased_authentication; /* If true, permit ssh2 hostbased auth */
|
||||||
|
int hostbased_uses_name_from_packet_only; /* experimental */
|
||||||
int rsa_authentication; /* If true, permit RSA authentication. */
|
int rsa_authentication; /* If true, permit RSA authentication. */
|
||||||
int dsa_authentication; /* If true, permit DSA authentication. */
|
|
||||||
#if defined(KRB4) || defined(KRB5)
|
#if defined(KRB4) || defined(KRB5)
|
||||||
int kerberos_authentication; /* If true, permit Kerberos auth. */
|
int kerberos_authentication; /* If true, permit Kerberos auth. */
|
||||||
#endif /* KRB4 || KRB5 */
|
#endif /* KRB4 || KRB5 */
|
||||||
|
int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */
|
||||||
#ifdef KRB4
|
#ifdef KRB4
|
||||||
int krb4_or_local_passwd; /* If true, permit kerberos v4
|
int krb4_or_local_passwd; /* If true, permit kerberos v4
|
||||||
* and any other password
|
* and any other password
|
||||||
@ -85,21 +98,18 @@ typedef struct {
|
|||||||
int password_authentication; /* If true, permit password
|
int password_authentication; /* If true, permit password
|
||||||
* authentication. */
|
* authentication. */
|
||||||
int kbd_interactive_authentication; /* If true, permit */
|
int kbd_interactive_authentication; /* If true, permit */
|
||||||
#ifdef SKEY
|
int challenge_reponse_authentication;
|
||||||
int skey_authentication; /* If true, permit s/key
|
|
||||||
* authentication. */
|
|
||||||
#endif
|
|
||||||
int permit_empty_passwd; /* If false, do not permit empty
|
int permit_empty_passwd; /* If false, do not permit empty
|
||||||
* passwords. */
|
* passwords. */
|
||||||
int use_login; /* If true, login(1) is used */
|
int use_login; /* If true, login(1) is used */
|
||||||
int allow_tcp_forwarding;
|
int allow_tcp_forwarding;
|
||||||
unsigned int num_allow_users;
|
u_int num_allow_users;
|
||||||
char *allow_users[MAX_ALLOW_USERS];
|
char *allow_users[MAX_ALLOW_USERS];
|
||||||
unsigned int num_deny_users;
|
u_int num_deny_users;
|
||||||
char *deny_users[MAX_DENY_USERS];
|
char *deny_users[MAX_DENY_USERS];
|
||||||
unsigned int num_allow_groups;
|
u_int num_allow_groups;
|
||||||
char *allow_groups[MAX_ALLOW_GROUPS];
|
char *allow_groups[MAX_ALLOW_GROUPS];
|
||||||
unsigned int num_deny_groups;
|
u_int num_deny_groups;
|
||||||
char *deny_groups[MAX_DENY_GROUPS];
|
char *deny_groups[MAX_DENY_GROUPS];
|
||||||
unsigned int connections_per_period; /*
|
unsigned int connections_per_period; /*
|
||||||
* If not 0, number of sshd
|
* If not 0, number of sshd
|
||||||
@ -108,13 +118,24 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
unsigned int connections_period;
|
unsigned int connections_period;
|
||||||
|
|
||||||
unsigned int num_subsystems;
|
u_int num_subsystems;
|
||||||
char *subsystem_name[MAX_SUBSYSTEMS];
|
char *subsystem_name[MAX_SUBSYSTEMS];
|
||||||
char *subsystem_command[MAX_SUBSYSTEMS];
|
char *subsystem_command[MAX_SUBSYSTEMS];
|
||||||
|
|
||||||
int max_startups_begin;
|
int max_startups_begin;
|
||||||
int max_startups_rate;
|
int max_startups_rate;
|
||||||
int max_startups;
|
int max_startups;
|
||||||
|
char *banner; /* SSH-2 banner message */
|
||||||
|
int reverse_mapping_check; /* cross-check ip and dns */
|
||||||
|
int client_alive_interval; /*
|
||||||
|
* poke the client this often to
|
||||||
|
* see if it's still there
|
||||||
|
*/
|
||||||
|
int client_alive_count_max; /*
|
||||||
|
*If the client is unresponsive
|
||||||
|
* for this many intervals, above
|
||||||
|
* diconnect the session
|
||||||
|
*/
|
||||||
|
|
||||||
} ServerOptions;
|
} ServerOptions;
|
||||||
/*
|
/*
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*
|
*
|
||||||
* SSH2 support by Markus Friedl.
|
* SSH2 support by Markus Friedl.
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -36,24 +36,31 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
RCSID("$OpenBSD: serverloop.c,v 1.34 2000/10/27 07:32:18 markus Exp $");
|
RCSID("$OpenBSD: serverloop.c,v 1.61 2001/04/13 22:46:54 beck Exp $");
|
||||||
|
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "ssh.h"
|
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "log.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "pty.h"
|
#include "sshpty.h"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "ssh1.h"
|
||||||
#include "ssh2.h"
|
#include "ssh2.h"
|
||||||
|
#include "auth.h"
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
#include "dispatch.h"
|
#include "dispatch.h"
|
||||||
#include "auth-options.h"
|
#include "auth-options.h"
|
||||||
|
#include "serverloop.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "kex.h"
|
||||||
|
|
||||||
extern ServerOptions options;
|
extern ServerOptions options;
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
extern Kex *xxx_kex;
|
||||||
|
|
||||||
static Buffer stdin_buffer; /* Buffer for stdin data. */
|
static Buffer stdin_buffer; /* Buffer for stdin data. */
|
||||||
static Buffer stdout_buffer; /* Buffer for stdout data. */
|
static Buffer stdout_buffer; /* Buffer for stdout data. */
|
||||||
static Buffer stderr_buffer; /* Buffer for stderr data. */
|
static Buffer stderr_buffer; /* Buffer for stderr data. */
|
||||||
@ -71,8 +78,8 @@ static int fderr_eof = 0; /* EOF encountered readung from fderr. */
|
|||||||
static int fdin_is_tty = 0; /* fdin points to a tty. */
|
static int fdin_is_tty = 0; /* fdin points to a tty. */
|
||||||
static int connection_in; /* Connection to client (input). */
|
static int connection_in; /* Connection to client (input). */
|
||||||
static int connection_out; /* Connection to client (output). */
|
static int connection_out; /* Connection to client (output). */
|
||||||
static unsigned int buffer_high;/* "Soft" max buffer size. */
|
static int connection_closed = 0; /* Connection to client closed. */
|
||||||
static int max_fd; /* Max file descriptor number for select(). */
|
static u_int buffer_high; /* "Soft" max buffer size. */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This SIGCHLD kludge is used to detect when the child exits. The server
|
* This SIGCHLD kludge is used to detect when the child exits. The server
|
||||||
@ -85,6 +92,8 @@ static volatile int child_wait_status; /* Status from wait(). */
|
|||||||
|
|
||||||
void server_init_dispatch(void);
|
void server_init_dispatch(void);
|
||||||
|
|
||||||
|
int client_alive_timeouts = 0;
|
||||||
|
|
||||||
void
|
void
|
||||||
sigchld_handler(int sig)
|
sigchld_handler(int sig)
|
||||||
{
|
{
|
||||||
@ -119,7 +128,7 @@ sigchld_handler2(int sig)
|
|||||||
* to the client.
|
* to the client.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
make_packets_from_stderr_data()
|
make_packets_from_stderr_data(void)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
@ -148,7 +157,7 @@ make_packets_from_stderr_data()
|
|||||||
* client.
|
* client.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
make_packets_from_stdout_data()
|
make_packets_from_stdout_data(void)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
@ -162,7 +171,7 @@ make_packets_from_stdout_data()
|
|||||||
} else {
|
} else {
|
||||||
/* Keep the packets at reasonable size. */
|
/* Keep the packets at reasonable size. */
|
||||||
if (len > packet_get_maxsize())
|
if (len > packet_get_maxsize())
|
||||||
len = packet_get_maxsize();
|
len = packet_get_maxsize();
|
||||||
}
|
}
|
||||||
packet_start(SSH_SMSG_STDOUT_DATA);
|
packet_start(SSH_SMSG_STDOUT_DATA);
|
||||||
packet_put_string(buffer_ptr(&stdout_buffer), len);
|
packet_put_string(buffer_ptr(&stdout_buffer), len);
|
||||||
@ -179,23 +188,37 @@ make_packets_from_stdout_data()
|
|||||||
* for the duration of the wait (0 = infinite).
|
* for the duration of the wait (0 = infinite).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
wait_until_can_do_something(fd_set * readset, fd_set * writeset,
|
wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
|
||||||
unsigned int max_time_milliseconds)
|
u_int max_time_milliseconds)
|
||||||
{
|
{
|
||||||
struct timeval tv, *tvp;
|
struct timeval tv, *tvp;
|
||||||
int ret;
|
int ret;
|
||||||
|
int client_alive_scheduled = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if using client_alive, set the max timeout accordingly,
|
||||||
|
* and indicate that this particular timeout was for client
|
||||||
|
* alive by setting the client_alive_scheduled flag.
|
||||||
|
*
|
||||||
|
* this could be randomized somewhat to make traffic
|
||||||
|
* analysis more difficult, but we're not doing it yet.
|
||||||
|
*/
|
||||||
|
if (max_time_milliseconds == 0 && options.client_alive_interval) {
|
||||||
|
client_alive_scheduled = 1;
|
||||||
|
max_time_milliseconds = options.client_alive_interval * 1000;
|
||||||
|
} else
|
||||||
|
client_alive_scheduled = 0;
|
||||||
|
|
||||||
/* When select fails we restart from here. */
|
/* When select fails we restart from here. */
|
||||||
retry_select:
|
retry_select:
|
||||||
|
|
||||||
/* Initialize select() masks. */
|
/* Allocate and update select() masks for channel descriptors. */
|
||||||
FD_ZERO(readset);
|
channel_prepare_select(readsetp, writesetp, maxfdp, 0);
|
||||||
FD_ZERO(writeset);
|
|
||||||
|
|
||||||
if (compat20) {
|
if (compat20) {
|
||||||
/* wrong: bad condition XXX */
|
/* wrong: bad condition XXX */
|
||||||
if (channel_not_very_much_buffered_data())
|
if (channel_not_very_much_buffered_data())
|
||||||
FD_SET(connection_in, readset);
|
FD_SET(connection_in, *readsetp);
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Read packets from the client unless we have too much
|
* Read packets from the client unless we have too much
|
||||||
@ -203,44 +226,38 @@ wait_until_can_do_something(fd_set * readset, fd_set * writeset,
|
|||||||
*/
|
*/
|
||||||
if (buffer_len(&stdin_buffer) < buffer_high &&
|
if (buffer_len(&stdin_buffer) < buffer_high &&
|
||||||
channel_not_very_much_buffered_data())
|
channel_not_very_much_buffered_data())
|
||||||
FD_SET(connection_in, readset);
|
FD_SET(connection_in, *readsetp);
|
||||||
/*
|
/*
|
||||||
* If there is not too much data already buffered going to
|
* If there is not too much data already buffered going to
|
||||||
* the client, try to get some more data from the program.
|
* the client, try to get some more data from the program.
|
||||||
*/
|
*/
|
||||||
if (packet_not_very_much_data_to_write()) {
|
if (packet_not_very_much_data_to_write()) {
|
||||||
if (!fdout_eof)
|
if (!fdout_eof)
|
||||||
FD_SET(fdout, readset);
|
FD_SET(fdout, *readsetp);
|
||||||
if (!fderr_eof)
|
if (!fderr_eof)
|
||||||
FD_SET(fderr, readset);
|
FD_SET(fderr, *readsetp);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If we have buffered data, try to write some of that data
|
* If we have buffered data, try to write some of that data
|
||||||
* to the program.
|
* to the program.
|
||||||
*/
|
*/
|
||||||
if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
|
if (fdin != -1 && buffer_len(&stdin_buffer) > 0)
|
||||||
FD_SET(fdin, writeset);
|
FD_SET(fdin, *writesetp);
|
||||||
}
|
}
|
||||||
/* Set masks for channel descriptors. */
|
|
||||||
channel_prepare_select(readset, writeset);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have buffered packet data going to the client, mark that
|
* If we have buffered packet data going to the client, mark that
|
||||||
* descriptor.
|
* descriptor.
|
||||||
*/
|
*/
|
||||||
if (packet_have_data_to_write())
|
if (packet_have_data_to_write())
|
||||||
FD_SET(connection_out, writeset);
|
FD_SET(connection_out, *writesetp);
|
||||||
|
|
||||||
/* Update the maximum descriptor number if appropriate. */
|
|
||||||
if (channel_max_fd() > max_fd)
|
|
||||||
max_fd = channel_max_fd();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If child has terminated and there is enough buffer space to read
|
* If child has terminated and there is enough buffer space to read
|
||||||
* from it, then read as much as is available and exit.
|
* from it, then read as much as is available and exit.
|
||||||
*/
|
*/
|
||||||
if (child_terminated && packet_not_very_much_data_to_write())
|
if (child_terminated && packet_not_very_much_data_to_write())
|
||||||
if (max_time_milliseconds == 0)
|
if (max_time_milliseconds == 0 || client_alive_scheduled)
|
||||||
max_time_milliseconds = 100;
|
max_time_milliseconds = 100;
|
||||||
|
|
||||||
if (max_time_milliseconds == 0)
|
if (max_time_milliseconds == 0)
|
||||||
@ -251,17 +268,41 @@ wait_until_can_do_something(fd_set * readset, fd_set * writeset,
|
|||||||
tvp = &tv;
|
tvp = &tv;
|
||||||
}
|
}
|
||||||
if (tvp!=NULL)
|
if (tvp!=NULL)
|
||||||
debug("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds);
|
debug3("tvp!=NULL kid %d mili %d", child_terminated, max_time_milliseconds);
|
||||||
|
|
||||||
/* Wait for something to happen, or the timeout to expire. */
|
/* Wait for something to happen, or the timeout to expire. */
|
||||||
ret = select(max_fd + 1, readset, writeset, NULL, tvp);
|
ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret == -1) {
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
error("select: %.100s", strerror(errno));
|
error("select: %.100s", strerror(errno));
|
||||||
else
|
else
|
||||||
goto retry_select;
|
goto retry_select;
|
||||||
}
|
}
|
||||||
|
if (ret == 0 && client_alive_scheduled) {
|
||||||
|
/* timeout, check to see how many we have had */
|
||||||
|
client_alive_timeouts++;
|
||||||
|
|
||||||
|
if (client_alive_timeouts > options.client_alive_count_max ) {
|
||||||
|
packet_disconnect(
|
||||||
|
"Timeout, your session not responding.");
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* send a bogus channel request with "wantreply"
|
||||||
|
* we should get back a failure
|
||||||
|
*/
|
||||||
|
int id;
|
||||||
|
|
||||||
|
id = channel_find_open();
|
||||||
|
if (id != -1) {
|
||||||
|
channel_request_start(id,
|
||||||
|
"keepalive@openssh.com", 1);
|
||||||
|
packet_send();
|
||||||
|
} else
|
||||||
|
packet_disconnect(
|
||||||
|
"No open channels after timeout!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -279,6 +320,9 @@ process_input(fd_set * readset)
|
|||||||
len = read(connection_in, buf, sizeof(buf));
|
len = read(connection_in, buf, sizeof(buf));
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
verbose("Connection closed by remote host.");
|
verbose("Connection closed by remote host.");
|
||||||
|
connection_closed = 1;
|
||||||
|
if (compat20)
|
||||||
|
return;
|
||||||
fatal_cleanup();
|
fatal_cleanup();
|
||||||
} else if (len < 0) {
|
} else if (len < 0) {
|
||||||
if (errno != EINTR && errno != EAGAIN) {
|
if (errno != EINTR && errno != EAGAIN) {
|
||||||
@ -351,9 +395,7 @@ process_output(fd_set * writeset)
|
|||||||
* Simulate echo to reduce the impact of
|
* Simulate echo to reduce the impact of
|
||||||
* traffic analysis
|
* traffic analysis
|
||||||
*/
|
*/
|
||||||
packet_start(SSH_MSG_IGNORE);
|
packet_send_ignore(len);
|
||||||
memset(buffer_ptr(&stdin_buffer), 0, len);
|
|
||||||
packet_put_string(buffer_ptr(&stdin_buffer), len);
|
|
||||||
packet_send();
|
packet_send();
|
||||||
}
|
}
|
||||||
/* Consume the data from the buffer. */
|
/* Consume the data from the buffer. */
|
||||||
@ -372,7 +414,7 @@ process_output(fd_set * writeset)
|
|||||||
* This is used when the program terminates.
|
* This is used when the program terminates.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
drain_output()
|
drain_output(void)
|
||||||
{
|
{
|
||||||
/* Send any buffered stdout data to the client. */
|
/* Send any buffered stdout data to the client. */
|
||||||
if (buffer_len(&stdout_buffer) > 0) {
|
if (buffer_len(&stdout_buffer) > 0) {
|
||||||
@ -397,9 +439,9 @@ drain_output()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
process_buffered_input_packets()
|
process_buffered_input_packets(void)
|
||||||
{
|
{
|
||||||
dispatch_run(DISPATCH_NONBLOCK, NULL, NULL);
|
dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -412,13 +454,14 @@ process_buffered_input_packets()
|
|||||||
void
|
void
|
||||||
server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
|
server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
|
||||||
{
|
{
|
||||||
fd_set readset, writeset;
|
fd_set *readset = NULL, *writeset = NULL;
|
||||||
|
int max_fd;
|
||||||
int wait_status; /* Status returned by wait(). */
|
int wait_status; /* Status returned by wait(). */
|
||||||
pid_t wait_pid; /* pid returned by wait(). */
|
pid_t wait_pid; /* pid returned by wait(). */
|
||||||
int waiting_termination = 0; /* Have displayed waiting close message. */
|
int waiting_termination = 0; /* Have displayed waiting close message. */
|
||||||
unsigned int max_time_milliseconds;
|
u_int max_time_milliseconds;
|
||||||
unsigned int previous_stdout_buffer_bytes;
|
u_int previous_stdout_buffer_bytes;
|
||||||
unsigned int stdout_buffer_bytes;
|
u_int stdout_buffer_bytes;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
debug("Entering interactive session.");
|
debug("Entering interactive session.");
|
||||||
@ -455,15 +498,11 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
|
|||||||
buffer_high = 64 * 1024;
|
buffer_high = 64 * 1024;
|
||||||
|
|
||||||
/* Initialize max_fd to the maximum of the known file descriptors. */
|
/* Initialize max_fd to the maximum of the known file descriptors. */
|
||||||
max_fd = fdin;
|
max_fd = MAX(fdin, fdout);
|
||||||
if (fdout > max_fd)
|
if (fderr != -1)
|
||||||
max_fd = fdout;
|
max_fd = MAX(max_fd, fderr);
|
||||||
if (fderr != -1 && fderr > max_fd)
|
max_fd = MAX(max_fd, connection_in);
|
||||||
max_fd = fderr;
|
max_fd = MAX(max_fd, connection_out);
|
||||||
if (connection_in > max_fd)
|
|
||||||
max_fd = connection_in;
|
|
||||||
if (connection_out > max_fd)
|
|
||||||
max_fd = connection_out;
|
|
||||||
|
|
||||||
/* Initialize Initialize buffers. */
|
/* Initialize Initialize buffers. */
|
||||||
buffer_init(&stdin_buffer);
|
buffer_init(&stdin_buffer);
|
||||||
@ -550,18 +589,22 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Sleep in select() until we can do something. */
|
/* Sleep in select() until we can do something. */
|
||||||
wait_until_can_do_something(&readset, &writeset,
|
wait_until_can_do_something(&readset, &writeset, &max_fd,
|
||||||
max_time_milliseconds);
|
max_time_milliseconds);
|
||||||
|
|
||||||
/* Process any channel events. */
|
/* Process any channel events. */
|
||||||
channel_after_select(&readset, &writeset);
|
channel_after_select(readset, writeset);
|
||||||
|
|
||||||
/* Process input from the client and from program stdout/stderr. */
|
/* Process input from the client and from program stdout/stderr. */
|
||||||
process_input(&readset);
|
process_input(readset);
|
||||||
|
|
||||||
/* Process output to the client and to program stdin. */
|
/* Process output to the client and to program stdin. */
|
||||||
process_output(&writeset);
|
process_output(writeset);
|
||||||
}
|
}
|
||||||
|
if (readset)
|
||||||
|
xfree(readset);
|
||||||
|
if (writeset)
|
||||||
|
xfree(writeset);
|
||||||
|
|
||||||
/* Cleanup and termination code. */
|
/* Cleanup and termination code. */
|
||||||
|
|
||||||
@ -594,7 +637,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
|
|||||||
|
|
||||||
/* Wait for the child to exit. Get its exit status. */
|
/* Wait for the child to exit. Get its exit status. */
|
||||||
wait_pid = wait(&wait_status);
|
wait_pid = wait(&wait_status);
|
||||||
if (wait_pid < 0) {
|
if (wait_pid == -1) {
|
||||||
/*
|
/*
|
||||||
* It is possible that the wait was handled by SIGCHLD
|
* It is possible that the wait was handled by SIGCHLD
|
||||||
* handler. This may result in either: this call
|
* handler. This may result in either: this call
|
||||||
@ -652,9 +695,8 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
|
|||||||
void
|
void
|
||||||
server_loop2(void)
|
server_loop2(void)
|
||||||
{
|
{
|
||||||
fd_set readset, writeset;
|
fd_set *readset = NULL, *writeset = NULL;
|
||||||
int had_channel = 0;
|
int rekeying = 0, max_fd, status;
|
||||||
int status;
|
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
debug("Entering interactive session for SSH2.");
|
debug("Entering interactive session for SSH2.");
|
||||||
@ -663,42 +705,61 @@ server_loop2(void)
|
|||||||
child_terminated = 0;
|
child_terminated = 0;
|
||||||
connection_in = packet_get_connection_in();
|
connection_in = packet_get_connection_in();
|
||||||
connection_out = packet_get_connection_out();
|
connection_out = packet_get_connection_out();
|
||||||
max_fd = connection_in;
|
|
||||||
if (connection_out > max_fd)
|
max_fd = MAX(connection_in, connection_out);
|
||||||
max_fd = connection_out;
|
|
||||||
server_init_dispatch();
|
server_init_dispatch();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
process_buffered_input_packets();
|
process_buffered_input_packets();
|
||||||
if (!had_channel && channel_still_open())
|
|
||||||
had_channel = 1;
|
rekeying = (xxx_kex != NULL && !xxx_kex->done);
|
||||||
if (had_channel && !channel_still_open()) {
|
|
||||||
debug("!channel_still_open.");
|
if (!rekeying && packet_not_very_much_data_to_write())
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (packet_not_very_much_data_to_write())
|
|
||||||
channel_output_poll();
|
channel_output_poll();
|
||||||
wait_until_can_do_something(&readset, &writeset, 0);
|
wait_until_can_do_something(&readset, &writeset, &max_fd,
|
||||||
|
rekeying);
|
||||||
if (child_terminated) {
|
if (child_terminated) {
|
||||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
|
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
|
||||||
session_close_by_pid(pid, status);
|
session_close_by_pid(pid, status);
|
||||||
child_terminated = 0;
|
child_terminated = 0;
|
||||||
}
|
}
|
||||||
channel_after_select(&readset, &writeset);
|
if (!rekeying)
|
||||||
process_input(&readset);
|
channel_after_select(readset, writeset);
|
||||||
process_output(&writeset);
|
process_input(readset);
|
||||||
|
if (connection_closed)
|
||||||
|
break;
|
||||||
|
process_output(writeset);
|
||||||
}
|
}
|
||||||
|
if (readset)
|
||||||
|
xfree(readset);
|
||||||
|
if (writeset)
|
||||||
|
xfree(writeset);
|
||||||
|
|
||||||
signal(SIGCHLD, SIG_DFL);
|
signal(SIGCHLD, SIG_DFL);
|
||||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
|
while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
|
||||||
session_close_by_pid(pid, status);
|
session_close_by_pid(pid, status);
|
||||||
channel_stop_listening();
|
channel_stop_listening();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_input_channel_failure(int type, int plen, void *ctxt)
|
||||||
|
{
|
||||||
|
debug("Got CHANNEL_FAILURE for keepalive");
|
||||||
|
/*
|
||||||
|
* reset timeout, since we got a sane answer from the client.
|
||||||
|
* even if this was generated by something other than
|
||||||
|
* the bogus CHANNEL_REQUEST we send for keepalives.
|
||||||
|
*/
|
||||||
|
client_alive_timeouts = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
server_input_stdin_data(int type, int plen, void *ctxt)
|
server_input_stdin_data(int type, int plen, void *ctxt)
|
||||||
{
|
{
|
||||||
char *data;
|
char *data;
|
||||||
unsigned int data_len;
|
u_int data_len;
|
||||||
|
|
||||||
/* Stdin data from the client. Append it to the buffer. */
|
/* Stdin data from the client. Append it to the buffer. */
|
||||||
/* Ignore any data if the client has closed stdin. */
|
/* Ignore any data if the client has closed stdin. */
|
||||||
@ -738,10 +799,10 @@ server_input_window_size(int type, int plen, void *ctxt)
|
|||||||
pty_change_window_size(fdin, row, col, xpixel, ypixel);
|
pty_change_window_size(fdin, row, col, xpixel, ypixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
Channel *
|
||||||
input_direct_tcpip(void)
|
server_request_direct_tcpip(char *ctype)
|
||||||
{
|
{
|
||||||
int sock;
|
int sock, newch;
|
||||||
char *target, *originator;
|
char *target, *originator;
|
||||||
int target_port, originator_port;
|
int target_port, originator_port;
|
||||||
|
|
||||||
@ -751,23 +812,47 @@ input_direct_tcpip(void)
|
|||||||
originator_port = packet_get_int();
|
originator_port = packet_get_int();
|
||||||
packet_done();
|
packet_done();
|
||||||
|
|
||||||
debug("open direct-tcpip: from %s port %d to %s port %d",
|
debug("server_request_direct_tcpip: originator %s port %d, target %s port %d",
|
||||||
originator, originator_port, target, target_port);
|
originator, originator_port, target, target_port);
|
||||||
|
|
||||||
/* XXX check permission */
|
/* XXX check permission */
|
||||||
if (no_port_forwarding_flag || !options.allow_tcp_forwarding) {
|
|
||||||
xfree(target);
|
|
||||||
xfree(originator);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
sock = channel_connect_to(target, target_port);
|
sock = channel_connect_to(target, target_port);
|
||||||
xfree(target);
|
xfree(target);
|
||||||
xfree(originator);
|
xfree(originator);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
return -1;
|
return NULL;
|
||||||
return channel_new("direct-tcpip", SSH_CHANNEL_OPEN,
|
newch = channel_new(ctype, SSH_CHANNEL_CONNECTING,
|
||||||
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
|
sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
|
||||||
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1);
|
CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1);
|
||||||
|
return (newch >= 0) ? channel_lookup(newch) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Channel *
|
||||||
|
server_request_session(char *ctype)
|
||||||
|
{
|
||||||
|
int newch;
|
||||||
|
|
||||||
|
debug("input_session_request");
|
||||||
|
packet_done();
|
||||||
|
/*
|
||||||
|
* A server session has no fd to read or write until a
|
||||||
|
* CHANNEL_REQUEST for a shell is made, so we set the type to
|
||||||
|
* SSH_CHANNEL_LARVAL. Additionally, a callback for handling all
|
||||||
|
* CHANNEL_REQUEST messages is registered.
|
||||||
|
*/
|
||||||
|
newch = channel_new(ctype, SSH_CHANNEL_LARVAL,
|
||||||
|
-1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT,
|
||||||
|
0, xstrdup("server-session"), 1);
|
||||||
|
if (session_open(newch) == 1) {
|
||||||
|
channel_register_callback(newch, SSH2_MSG_CHANNEL_REQUEST,
|
||||||
|
session_input_channel_req, (void *)0);
|
||||||
|
channel_register_cleanup(newch, session_close_by_channel);
|
||||||
|
return channel_lookup(newch);
|
||||||
|
} else {
|
||||||
|
debug("session open failed, free channel %d", newch);
|
||||||
|
channel_free(newch);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -775,8 +860,7 @@ server_input_channel_open(int type, int plen, void *ctxt)
|
|||||||
{
|
{
|
||||||
Channel *c = NULL;
|
Channel *c = NULL;
|
||||||
char *ctype;
|
char *ctype;
|
||||||
int id;
|
u_int len;
|
||||||
unsigned int len;
|
|
||||||
int rchan;
|
int rchan;
|
||||||
int rmaxpack;
|
int rmaxpack;
|
||||||
int rwindow;
|
int rwindow;
|
||||||
@ -790,34 +874,12 @@ server_input_channel_open(int type, int plen, void *ctxt)
|
|||||||
ctype, rchan, rwindow, rmaxpack);
|
ctype, rchan, rwindow, rmaxpack);
|
||||||
|
|
||||||
if (strcmp(ctype, "session") == 0) {
|
if (strcmp(ctype, "session") == 0) {
|
||||||
debug("open session");
|
c = server_request_session(ctype);
|
||||||
packet_done();
|
|
||||||
/*
|
|
||||||
* A server session has no fd to read or write
|
|
||||||
* until a CHANNEL_REQUEST for a shell is made,
|
|
||||||
* so we set the type to SSH_CHANNEL_LARVAL.
|
|
||||||
* Additionally, a callback for handling all
|
|
||||||
* CHANNEL_REQUEST messages is registered.
|
|
||||||
*/
|
|
||||||
id = channel_new(ctype, SSH_CHANNEL_LARVAL,
|
|
||||||
-1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT,
|
|
||||||
0, xstrdup("server-session"), 1);
|
|
||||||
if (session_open(id) == 1) {
|
|
||||||
channel_register_callback(id, SSH2_MSG_CHANNEL_REQUEST,
|
|
||||||
session_input_channel_req, (void *)0);
|
|
||||||
channel_register_cleanup(id, session_close_by_channel);
|
|
||||||
c = channel_lookup(id);
|
|
||||||
} else {
|
|
||||||
debug("session open failed, free channel %d", id);
|
|
||||||
channel_free(id);
|
|
||||||
}
|
|
||||||
} else if (strcmp(ctype, "direct-tcpip") == 0) {
|
} else if (strcmp(ctype, "direct-tcpip") == 0) {
|
||||||
id = input_direct_tcpip();
|
c = server_request_direct_tcpip(ctype);
|
||||||
if (id >= 0)
|
|
||||||
c = channel_lookup(id);
|
|
||||||
}
|
}
|
||||||
if (c != NULL) {
|
if (c != NULL) {
|
||||||
debug("confirm %s", ctype);
|
debug("server_input_channel_open: confirm %s", ctype);
|
||||||
c->remote_id = rchan;
|
c->remote_id = rchan;
|
||||||
c->remote_window = rwindow;
|
c->remote_window = rwindow;
|
||||||
c->remote_maxpacket = rmaxpack;
|
c->remote_maxpacket = rmaxpack;
|
||||||
@ -829,7 +891,7 @@ server_input_channel_open(int type, int plen, void *ctxt)
|
|||||||
packet_put_int(c->local_maxpacket);
|
packet_put_int(c->local_maxpacket);
|
||||||
packet_send();
|
packet_send();
|
||||||
} else {
|
} else {
|
||||||
debug("failure %s", ctype);
|
debug("server_input_channel_open: failure %s", ctype);
|
||||||
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
|
packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
|
||||||
packet_put_int(rchan);
|
packet_put_int(rchan);
|
||||||
packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
|
packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
|
||||||
@ -841,7 +903,57 @@ server_input_channel_open(int type, int plen, void *ctxt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_init_dispatch_20()
|
server_input_global_request(int type, int plen, void *ctxt)
|
||||||
|
{
|
||||||
|
char *rtype;
|
||||||
|
int want_reply;
|
||||||
|
int success = 0;
|
||||||
|
|
||||||
|
rtype = packet_get_string(NULL);
|
||||||
|
want_reply = packet_get_char();
|
||||||
|
debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply);
|
||||||
|
|
||||||
|
/* -R style forwarding */
|
||||||
|
if (strcmp(rtype, "tcpip-forward") == 0) {
|
||||||
|
struct passwd *pw;
|
||||||
|
char *listen_address;
|
||||||
|
u_short listen_port;
|
||||||
|
|
||||||
|
pw = auth_get_user();
|
||||||
|
if (pw == NULL)
|
||||||
|
fatal("server_input_global_request: no user");
|
||||||
|
listen_address = packet_get_string(NULL); /* XXX currently ignored */
|
||||||
|
listen_port = (u_short)packet_get_int();
|
||||||
|
debug("server_input_global_request: tcpip-forward listen %s port %d",
|
||||||
|
listen_address, listen_port);
|
||||||
|
|
||||||
|
/* check permissions */
|
||||||
|
if (!options.allow_tcp_forwarding ||
|
||||||
|
no_port_forwarding_flag ||
|
||||||
|
(listen_port < IPPORT_RESERVED && pw->pw_uid != 0)) {
|
||||||
|
success = 0;
|
||||||
|
packet_send_debug("Server has disabled port forwarding.");
|
||||||
|
} else {
|
||||||
|
/* Start listening on the port */
|
||||||
|
success = channel_request_forwarding(
|
||||||
|
listen_address, listen_port,
|
||||||
|
/*unspec host_to_connect*/ "<unspec host>",
|
||||||
|
/*unspec port_to_connect*/ 0,
|
||||||
|
options.gateway_ports, /*remote*/ 1);
|
||||||
|
}
|
||||||
|
xfree(listen_address);
|
||||||
|
}
|
||||||
|
if (want_reply) {
|
||||||
|
packet_start(success ?
|
||||||
|
SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
|
||||||
|
packet_send();
|
||||||
|
packet_write_wait();
|
||||||
|
}
|
||||||
|
xfree(rtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
server_init_dispatch_20(void)
|
||||||
{
|
{
|
||||||
debug("server_init_dispatch_20");
|
debug("server_init_dispatch_20");
|
||||||
dispatch_init(&dispatch_protocol_error);
|
dispatch_init(&dispatch_protocol_error);
|
||||||
@ -854,9 +966,14 @@ server_init_dispatch_20()
|
|||||||
dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
|
dispatch_set(SSH2_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
|
||||||
dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
|
dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
|
||||||
dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
|
dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
|
||||||
|
dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
|
||||||
|
/* client_alive */
|
||||||
|
dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_channel_failure);
|
||||||
|
/* rekeying */
|
||||||
|
dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
server_init_dispatch_13()
|
server_init_dispatch_13(void)
|
||||||
{
|
{
|
||||||
debug("server_init_dispatch_13");
|
debug("server_init_dispatch_13");
|
||||||
dispatch_init(NULL);
|
dispatch_init(NULL);
|
||||||
@ -871,7 +988,7 @@ server_init_dispatch_13()
|
|||||||
dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
|
dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
server_init_dispatch_15()
|
server_init_dispatch_15(void)
|
||||||
{
|
{
|
||||||
server_init_dispatch_13();
|
server_init_dispatch_13();
|
||||||
debug("server_init_dispatch_15");
|
debug("server_init_dispatch_15");
|
||||||
@ -879,7 +996,7 @@ server_init_dispatch_15()
|
|||||||
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
|
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
server_init_dispatch()
|
server_init_dispatch(void)
|
||||||
{
|
{
|
||||||
if (compat20)
|
if (compat20)
|
||||||
server_init_dispatch_20();
|
server_init_dispatch_20();
|
||||||
@ -888,3 +1005,4 @@ server_init_dispatch()
|
|||||||
else
|
else
|
||||||
server_init_dispatch_15();
|
server_init_dispatch_15();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*
|
*
|
||||||
* SSH2 implementation,
|
* SSH2 implementation,
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -36,33 +36,42 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
RCSID("$OpenBSD: ssh-add.c,v 1.22 2000/09/07 20:27:54 deraadt Exp $");
|
RCSID("$OpenBSD: ssh-add.c,v 1.36 2001/04/18 21:57:42 markus Exp $");
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
|
|
||||||
#include "rsa.h"
|
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
|
#include "rsa.h"
|
||||||
|
#include "log.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "readpass.h"
|
||||||
|
|
||||||
|
/* we keep a cache of one passphrases */
|
||||||
|
static char *pass = NULL;
|
||||||
|
void
|
||||||
|
clear_pass(void)
|
||||||
|
{
|
||||||
|
if (pass) {
|
||||||
|
memset(pass, 0, strlen(pass));
|
||||||
|
xfree(pass);
|
||||||
|
pass = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
delete_file(AuthenticationConnection *ac, const char *filename)
|
delete_file(AuthenticationConnection *ac, const char *filename)
|
||||||
{
|
{
|
||||||
Key *public;
|
Key *public;
|
||||||
char *comment;
|
char *comment = NULL;
|
||||||
|
|
||||||
public = key_new(KEY_RSA);
|
public = key_load_public(filename, &comment);
|
||||||
if (!load_public_key(filename, public, &comment)) {
|
if (public == NULL) {
|
||||||
key_free(public);
|
printf("Bad key file %s\n", filename);
|
||||||
public = key_new(KEY_DSA);
|
return;
|
||||||
if (!try_load_public_key(filename, public, &comment)) {
|
|
||||||
printf("Bad key file %s\n", filename);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ssh_remove_identity(ac, public))
|
if (ssh_remove_identity(ac, public))
|
||||||
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
|
fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment);
|
||||||
@ -86,129 +95,61 @@ delete_all(AuthenticationConnection *ac)
|
|||||||
if (success)
|
if (success)
|
||||||
fprintf(stderr, "All identities removed.\n");
|
fprintf(stderr, "All identities removed.\n");
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Failed to remove all identitities.\n");
|
fprintf(stderr, "Failed to remove all identities.\n");
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
ssh_askpass(char *askpass, char *msg)
|
|
||||||
{
|
|
||||||
pid_t pid;
|
|
||||||
size_t len;
|
|
||||||
char *nl, *pass;
|
|
||||||
int p[2], status;
|
|
||||||
char buf[1024];
|
|
||||||
|
|
||||||
if (askpass == NULL)
|
|
||||||
fatal("internal error: askpass undefined");
|
|
||||||
if (pipe(p) < 0)
|
|
||||||
fatal("ssh_askpass: pipe: %s", strerror(errno));
|
|
||||||
fflush(stdout);
|
|
||||||
fflush(stderr);
|
|
||||||
if ((pid = fork()) < 0)
|
|
||||||
fatal("ssh_askpass: fork: %s", strerror(errno));
|
|
||||||
if (pid == 0) {
|
|
||||||
close(p[0]);
|
|
||||||
if (dup2(p[1], STDOUT_FILENO) < 0)
|
|
||||||
fatal("ssh_askpass: dup2: %s", strerror(errno));
|
|
||||||
execlp(askpass, askpass, msg, (char *) 0);
|
|
||||||
fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
|
|
||||||
}
|
|
||||||
close(p[1]);
|
|
||||||
len = read(p[0], buf, sizeof buf);
|
|
||||||
close(p[0]);
|
|
||||||
while (waitpid(pid, &status, 0) < 0)
|
|
||||||
if (errno != EINTR)
|
|
||||||
break;
|
|
||||||
if (len <= 1)
|
|
||||||
return xstrdup("");
|
|
||||||
nl = strchr(buf, '\n');
|
|
||||||
if (nl)
|
|
||||||
*nl = '\0';
|
|
||||||
pass = xstrdup(buf);
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
return pass;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
add_file(AuthenticationConnection *ac, const char *filename)
|
add_file(AuthenticationConnection *ac, const char *filename)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
Key *public;
|
|
||||||
Key *private;
|
Key *private;
|
||||||
char *saved_comment, *comment, *askpass = NULL;
|
char *comment = NULL;
|
||||||
char buf[1024], msg[1024];
|
char msg[1024];
|
||||||
int success;
|
|
||||||
int interactive = isatty(STDIN_FILENO);
|
|
||||||
int type = KEY_RSA;
|
|
||||||
|
|
||||||
if (stat(filename, &st) < 0) {
|
if (stat(filename, &st) < 0) {
|
||||||
perror(filename);
|
perror(filename);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* try to load the public key. right now this only works for RSA,
|
|
||||||
* since DSA keys are fully encrypted
|
|
||||||
*/
|
|
||||||
public = key_new(KEY_RSA);
|
|
||||||
if (!load_public_key(filename, public, &saved_comment)) {
|
|
||||||
/* ok, so we will asume this is a DSA key */
|
|
||||||
type = KEY_DSA;
|
|
||||||
saved_comment = xstrdup(filename);
|
|
||||||
}
|
|
||||||
key_free(public);
|
|
||||||
|
|
||||||
if (!interactive && getenv("DISPLAY")) {
|
|
||||||
if (getenv(SSH_ASKPASS_ENV))
|
|
||||||
askpass = getenv(SSH_ASKPASS_ENV);
|
|
||||||
else
|
|
||||||
askpass = SSH_ASKPASS_DEFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* At first, try empty passphrase */
|
/* At first, try empty passphrase */
|
||||||
private = key_new(type);
|
private = key_load_private(filename, "", &comment);
|
||||||
success = load_private_key(filename, "", private, &comment);
|
if (comment == NULL)
|
||||||
if (!success) {
|
comment = xstrdup(filename);
|
||||||
|
/* try last */
|
||||||
|
if (private == NULL && pass != NULL)
|
||||||
|
private = key_load_private(filename, pass, NULL);
|
||||||
|
if (private == NULL) {
|
||||||
|
/* clear passphrase since it did not work */
|
||||||
|
clear_pass();
|
||||||
printf("Need passphrase for %.200s\n", filename);
|
printf("Need passphrase for %.200s\n", filename);
|
||||||
if (!interactive && askpass == NULL) {
|
snprintf(msg, sizeof msg, "Enter passphrase for %.200s ",
|
||||||
xfree(saved_comment);
|
comment);
|
||||||
return;
|
|
||||||
}
|
|
||||||
snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment);
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char *pass;
|
pass = read_passphrase(msg, 1);
|
||||||
if (interactive) {
|
|
||||||
snprintf(buf, sizeof buf, "%s: ", msg);
|
|
||||||
pass = read_passphrase(buf, 1);
|
|
||||||
} else {
|
|
||||||
pass = ssh_askpass(askpass, msg);
|
|
||||||
}
|
|
||||||
if (strcmp(pass, "") == 0) {
|
if (strcmp(pass, "") == 0) {
|
||||||
xfree(pass);
|
clear_pass();
|
||||||
xfree(saved_comment);
|
xfree(comment);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
success = load_private_key(filename, pass, private, &comment);
|
private = key_load_private(filename, pass, &comment);
|
||||||
memset(pass, 0, strlen(pass));
|
if (private != NULL)
|
||||||
xfree(pass);
|
|
||||||
if (success)
|
|
||||||
break;
|
break;
|
||||||
strlcpy(msg, "Bad passphrase, try again", sizeof msg);
|
clear_pass();
|
||||||
|
strlcpy(msg, "Bad passphrase, try again ", sizeof msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xfree(comment);
|
if (ssh_add_identity(ac, private, comment))
|
||||||
if (ssh_add_identity(ac, private, saved_comment))
|
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
|
||||||
fprintf(stderr, "Identity added: %s (%s)\n", filename, saved_comment);
|
|
||||||
else
|
else
|
||||||
fprintf(stderr, "Could not add identity: %s\n", filename);
|
fprintf(stderr, "Could not add identity: %s\n", filename);
|
||||||
|
xfree(comment);
|
||||||
key_free(private);
|
key_free(private);
|
||||||
xfree(saved_comment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
list_identities(AuthenticationConnection *ac, int fp)
|
list_identities(AuthenticationConnection *ac, int do_fp)
|
||||||
{
|
{
|
||||||
Key *key;
|
Key *key;
|
||||||
char *comment;
|
char *comment, *fp;
|
||||||
int had_identities = 0;
|
int had_identities = 0;
|
||||||
int version;
|
int version;
|
||||||
|
|
||||||
@ -217,9 +158,12 @@ list_identities(AuthenticationConnection *ac, int fp)
|
|||||||
key != NULL;
|
key != NULL;
|
||||||
key = ssh_get_next_identity(ac, &comment, version)) {
|
key = ssh_get_next_identity(ac, &comment, version)) {
|
||||||
had_identities = 1;
|
had_identities = 1;
|
||||||
if (fp) {
|
if (do_fp) {
|
||||||
printf("%d %s %s\n",
|
fp = key_fingerprint(key, SSH_FP_MD5,
|
||||||
key_size(key), key_fingerprint(key), comment);
|
SSH_FP_HEX);
|
||||||
|
printf("%d %s %s (%s)\n",
|
||||||
|
key_size(key), fp, comment, key_type(key));
|
||||||
|
xfree(fp);
|
||||||
} else {
|
} else {
|
||||||
if (!key_write(key, stdout))
|
if (!key_write(key, stdout))
|
||||||
fprintf(stderr, "key_write failed");
|
fprintf(stderr, "key_write failed");
|
||||||
@ -243,16 +187,7 @@ main(int argc, char **argv)
|
|||||||
int i;
|
int i;
|
||||||
int deleting = 0;
|
int deleting = 0;
|
||||||
|
|
||||||
/* check if RSA support exists */
|
SSLeay_add_all_algorithms();
|
||||||
if (rsa_alive() == 0) {
|
|
||||||
extern char *__progname;
|
|
||||||
|
|
||||||
fprintf(stderr,
|
|
||||||
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
|
|
||||||
__progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
SSLeay_add_all_algorithms();
|
|
||||||
|
|
||||||
/* At first, get a connection to the authentication agent. */
|
/* At first, get a connection to the authentication agent. */
|
||||||
ac = ssh_get_authentication_connection();
|
ac = ssh_get_authentication_connection();
|
||||||
@ -291,12 +226,13 @@ main(int argc, char **argv)
|
|||||||
ssh_close_authentication_connection(ac);
|
ssh_close_authentication_connection(ac);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY);
|
snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, _PATH_SSH_CLIENT_IDENTITY);
|
||||||
if (deleting)
|
if (deleting)
|
||||||
delete_file(ac, buf);
|
delete_file(ac, buf);
|
||||||
else
|
else
|
||||||
add_file(ac, buf);
|
add_file(ac, buf);
|
||||||
}
|
}
|
||||||
|
clear_pass();
|
||||||
ssh_close_authentication_connection(ac);
|
ssh_close_authentication_connection(ac);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $ */
|
/* $OpenBSD: ssh-agent.c,v 1.54 2001/04/03 13:56:11 stevesk Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
@ -13,7 +13,7 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*
|
*
|
||||||
* SSH2 implementation,
|
* SSH2 implementation,
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
@ -37,9 +37,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: ssh-agent.c,v 1.37 2000/09/21 11:07:51 markus Exp $");
|
RCSID("$OpenBSD: ssh-agent.c,v 1.54 2001/04/03 13:56:11 stevesk Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/md5.h>
|
||||||
|
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
@ -48,16 +51,12 @@ RCSID("$FreeBSD$");
|
|||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "getput.h"
|
#include "getput.h"
|
||||||
#include "mpaux.h"
|
#include "mpaux.h"
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <openssl/md5.h>
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "dsa.h"
|
#include "cipher.h"
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
@ -68,7 +67,7 @@ typedef struct {
|
|||||||
Buffer output;
|
Buffer output;
|
||||||
} SocketEntry;
|
} SocketEntry;
|
||||||
|
|
||||||
unsigned int sockets_alloc = 0;
|
u_int sockets_alloc = 0;
|
||||||
SocketEntry *sockets = NULL;
|
SocketEntry *sockets = NULL;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -95,6 +94,8 @@ char socket_dir[1024];
|
|||||||
|
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
|
int prepare_select(fd_set **, fd_set **, int *);
|
||||||
|
|
||||||
void
|
void
|
||||||
idtab_init(void)
|
idtab_init(void)
|
||||||
{
|
{
|
||||||
@ -144,14 +145,14 @@ process_request_identities(SocketEntry *e, int version)
|
|||||||
buffer_put_int(&msg, tab->nentries);
|
buffer_put_int(&msg, tab->nentries);
|
||||||
for (i = 0; i < tab->nentries; i++) {
|
for (i = 0; i < tab->nentries; i++) {
|
||||||
Identity *id = &tab->identities[i];
|
Identity *id = &tab->identities[i];
|
||||||
if (id->key->type == KEY_RSA) {
|
if (id->key->type == KEY_RSA1) {
|
||||||
buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
|
buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
|
||||||
buffer_put_bignum(&msg, id->key->rsa->e);
|
buffer_put_bignum(&msg, id->key->rsa->e);
|
||||||
buffer_put_bignum(&msg, id->key->rsa->n);
|
buffer_put_bignum(&msg, id->key->rsa->n);
|
||||||
} else {
|
} else {
|
||||||
unsigned char *blob;
|
u_char *blob;
|
||||||
unsigned int blen;
|
u_int blen;
|
||||||
dsa_make_key_blob(id->key, &blob, &blen);
|
key_to_blob(id->key, &blob, &blen);
|
||||||
buffer_put_string(&msg, blob, blen);
|
buffer_put_string(&msg, blob, blen);
|
||||||
xfree(blob);
|
xfree(blob);
|
||||||
}
|
}
|
||||||
@ -171,11 +172,11 @@ process_authentication_challenge1(SocketEntry *e)
|
|||||||
int i, len;
|
int i, len;
|
||||||
Buffer msg;
|
Buffer msg;
|
||||||
MD5_CTX md;
|
MD5_CTX md;
|
||||||
unsigned char buf[32], mdbuf[16], session_id[16];
|
u_char buf[32], mdbuf[16], session_id[16];
|
||||||
unsigned int response_type;
|
u_int response_type;
|
||||||
|
|
||||||
buffer_init(&msg);
|
buffer_init(&msg);
|
||||||
key = key_new(KEY_RSA);
|
key = key_new(KEY_RSA1);
|
||||||
challenge = BN_new();
|
challenge = BN_new();
|
||||||
|
|
||||||
buffer_get_int(&e->input); /* ignored */
|
buffer_get_int(&e->input); /* ignored */
|
||||||
@ -234,14 +235,14 @@ process_sign_request2(SocketEntry *e)
|
|||||||
{
|
{
|
||||||
extern int datafellows;
|
extern int datafellows;
|
||||||
Key *key, *private;
|
Key *key, *private;
|
||||||
unsigned char *blob, *data, *signature = NULL;
|
u_char *blob, *data, *signature = NULL;
|
||||||
unsigned int blen, dlen, slen = 0;
|
u_int blen, dlen, slen = 0;
|
||||||
int flags;
|
int flags;
|
||||||
Buffer msg;
|
Buffer msg;
|
||||||
int ok = -1;
|
int ok = -1;
|
||||||
|
|
||||||
datafellows = 0;
|
datafellows = 0;
|
||||||
|
|
||||||
blob = buffer_get_string(&e->input, &blen);
|
blob = buffer_get_string(&e->input, &blen);
|
||||||
data = buffer_get_string(&e->input, &dlen);
|
data = buffer_get_string(&e->input, &dlen);
|
||||||
|
|
||||||
@ -249,11 +250,11 @@ process_sign_request2(SocketEntry *e)
|
|||||||
if (flags & SSH_AGENT_OLD_SIGNATURE)
|
if (flags & SSH_AGENT_OLD_SIGNATURE)
|
||||||
datafellows = SSH_BUG_SIGBLOB;
|
datafellows = SSH_BUG_SIGBLOB;
|
||||||
|
|
||||||
key = dsa_key_from_blob(blob, blen);
|
key = key_from_blob(blob, blen);
|
||||||
if (key != NULL) {
|
if (key != NULL) {
|
||||||
private = lookup_private_key(key, NULL, 2);
|
private = lookup_private_key(key, NULL, 2);
|
||||||
if (private != NULL)
|
if (private != NULL)
|
||||||
ok = dsa_sign(private, &signature, &slen, data, dlen);
|
ok = key_sign(private, &signature, &slen, data, dlen);
|
||||||
}
|
}
|
||||||
key_free(key);
|
key_free(key);
|
||||||
buffer_init(&msg);
|
buffer_init(&msg);
|
||||||
@ -278,25 +279,25 @@ void
|
|||||||
process_remove_identity(SocketEntry *e, int version)
|
process_remove_identity(SocketEntry *e, int version)
|
||||||
{
|
{
|
||||||
Key *key = NULL, *private;
|
Key *key = NULL, *private;
|
||||||
unsigned char *blob;
|
u_char *blob;
|
||||||
unsigned int blen;
|
u_int blen;
|
||||||
unsigned int bits;
|
u_int bits;
|
||||||
int success = 0;
|
int success = 0;
|
||||||
|
|
||||||
switch(version){
|
switch(version){
|
||||||
case 1:
|
case 1:
|
||||||
key = key_new(KEY_RSA);
|
key = key_new(KEY_RSA1);
|
||||||
bits = buffer_get_int(&e->input);
|
bits = buffer_get_int(&e->input);
|
||||||
buffer_get_bignum(&e->input, key->rsa->e);
|
buffer_get_bignum(&e->input, key->rsa->e);
|
||||||
buffer_get_bignum(&e->input, key->rsa->n);
|
buffer_get_bignum(&e->input, key->rsa->n);
|
||||||
|
|
||||||
if (bits != key_size(key))
|
if (bits != key_size(key))
|
||||||
log("Warning: identity keysize mismatch: actual %d, announced %d",
|
log("Warning: identity keysize mismatch: actual %d, announced %d",
|
||||||
key_size(key), bits);
|
key_size(key), bits);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
blob = buffer_get_string(&e->input, &blen);
|
blob = buffer_get_string(&e->input, &blen);
|
||||||
key = dsa_key_from_blob(blob, blen);
|
key = key_from_blob(blob, blen);
|
||||||
xfree(blob);
|
xfree(blob);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -307,14 +308,24 @@ process_remove_identity(SocketEntry *e, int version)
|
|||||||
/*
|
/*
|
||||||
* We have this key. Free the old key. Since we
|
* We have this key. Free the old key. Since we
|
||||||
* don\'t want to leave empty slots in the middle of
|
* don\'t want to leave empty slots in the middle of
|
||||||
* the array, we actually free the key there and copy
|
* the array, we actually free the key there and move
|
||||||
* data from the last entry.
|
* all the entries between the empty slot and the end
|
||||||
|
* of the array.
|
||||||
*/
|
*/
|
||||||
Idtab *tab = idtab_lookup(version);
|
Idtab *tab = idtab_lookup(version);
|
||||||
key_free(tab->identities[idx].key);
|
key_free(tab->identities[idx].key);
|
||||||
xfree(tab->identities[idx].comment);
|
xfree(tab->identities[idx].comment);
|
||||||
if (idx != tab->nentries)
|
if (tab->nentries < 1)
|
||||||
tab->identities[idx] = tab->identities[tab->nentries];
|
fatal("process_remove_identity: "
|
||||||
|
"internal error: tab->nentries %d",
|
||||||
|
tab->nentries);
|
||||||
|
if (idx != tab->nentries - 1) {
|
||||||
|
int i;
|
||||||
|
for (i = idx; i < tab->nentries - 1; i++)
|
||||||
|
tab->identities[i] = tab->identities[i+1];
|
||||||
|
}
|
||||||
|
tab->identities[tab->nentries - 1].key = NULL;
|
||||||
|
tab->identities[tab->nentries - 1].comment = NULL;
|
||||||
tab->nentries--;
|
tab->nentries--;
|
||||||
success = 1;
|
success = 1;
|
||||||
}
|
}
|
||||||
@ -328,7 +339,7 @@ process_remove_identity(SocketEntry *e, int version)
|
|||||||
void
|
void
|
||||||
process_remove_all_identities(SocketEntry *e, int version)
|
process_remove_all_identities(SocketEntry *e, int version)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
u_int i;
|
||||||
Idtab *tab = idtab_lookup(version);
|
Idtab *tab = idtab_lookup(version);
|
||||||
|
|
||||||
/* Loop over all identities and clear the keys. */
|
/* Loop over all identities and clear the keys. */
|
||||||
@ -350,76 +361,58 @@ void
|
|||||||
process_add_identity(SocketEntry *e, int version)
|
process_add_identity(SocketEntry *e, int version)
|
||||||
{
|
{
|
||||||
Key *k = NULL;
|
Key *k = NULL;
|
||||||
RSA *rsa;
|
char *type_name;
|
||||||
BIGNUM *aux;
|
|
||||||
BN_CTX *ctx;
|
|
||||||
char *type;
|
|
||||||
char *comment;
|
char *comment;
|
||||||
int success = 0;
|
int type, success = 0;
|
||||||
Idtab *tab = idtab_lookup(version);
|
Idtab *tab = idtab_lookup(version);
|
||||||
|
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case 1:
|
case 1:
|
||||||
k = key_new(KEY_RSA);
|
k = key_new_private(KEY_RSA1);
|
||||||
rsa = k->rsa;
|
buffer_get_int(&e->input); /* ignored */
|
||||||
|
buffer_get_bignum(&e->input, k->rsa->n);
|
||||||
/* allocate mem for private key */
|
buffer_get_bignum(&e->input, k->rsa->e);
|
||||||
/* XXX rsa->n and rsa->e are already allocated */
|
buffer_get_bignum(&e->input, k->rsa->d);
|
||||||
rsa->d = BN_new();
|
buffer_get_bignum(&e->input, k->rsa->iqmp);
|
||||||
rsa->iqmp = BN_new();
|
|
||||||
rsa->q = BN_new();
|
|
||||||
rsa->p = BN_new();
|
|
||||||
rsa->dmq1 = BN_new();
|
|
||||||
rsa->dmp1 = BN_new();
|
|
||||||
|
|
||||||
buffer_get_int(&e->input); /* ignored */
|
|
||||||
|
|
||||||
buffer_get_bignum(&e->input, rsa->n);
|
|
||||||
buffer_get_bignum(&e->input, rsa->e);
|
|
||||||
buffer_get_bignum(&e->input, rsa->d);
|
|
||||||
buffer_get_bignum(&e->input, rsa->iqmp);
|
|
||||||
|
|
||||||
/* SSH and SSL have p and q swapped */
|
/* SSH and SSL have p and q swapped */
|
||||||
buffer_get_bignum(&e->input, rsa->q); /* p */
|
buffer_get_bignum(&e->input, k->rsa->q); /* p */
|
||||||
buffer_get_bignum(&e->input, rsa->p); /* q */
|
buffer_get_bignum(&e->input, k->rsa->p); /* q */
|
||||||
|
|
||||||
/* Generate additional parameters */
|
/* Generate additional parameters */
|
||||||
aux = BN_new();
|
generate_additional_parameters(k->rsa);
|
||||||
ctx = BN_CTX_new();
|
|
||||||
|
|
||||||
BN_sub(aux, rsa->q, BN_value_one());
|
|
||||||
BN_mod(rsa->dmq1, rsa->d, aux, ctx);
|
|
||||||
|
|
||||||
BN_sub(aux, rsa->p, BN_value_one());
|
|
||||||
BN_mod(rsa->dmp1, rsa->d, aux, ctx);
|
|
||||||
|
|
||||||
BN_clear_free(aux);
|
|
||||||
BN_CTX_free(ctx);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
type = buffer_get_string(&e->input, NULL);
|
type_name = buffer_get_string(&e->input, NULL);
|
||||||
if (strcmp(type, KEX_DSS)) {
|
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);
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Generate additional parameters */
|
||||||
|
generate_additional_parameters(k->rsa);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
buffer_clear(&e->input);
|
buffer_clear(&e->input);
|
||||||
xfree(type);
|
|
||||||
goto send;
|
goto send;
|
||||||
}
|
}
|
||||||
xfree(type);
|
|
||||||
|
|
||||||
k = key_new(KEY_DSA);
|
|
||||||
|
|
||||||
/* allocate mem for private key */
|
|
||||||
k->dsa->priv_key = BN_new();
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
comment = buffer_get_string(&e->input, NULL);
|
comment = buffer_get_string(&e->input, NULL);
|
||||||
if (k == NULL) {
|
if (k == NULL) {
|
||||||
xfree(comment);
|
xfree(comment);
|
||||||
@ -451,12 +444,12 @@ process_add_identity(SocketEntry *e, int version)
|
|||||||
void
|
void
|
||||||
process_message(SocketEntry *e)
|
process_message(SocketEntry *e)
|
||||||
{
|
{
|
||||||
unsigned int msg_len;
|
u_int msg_len;
|
||||||
unsigned int type;
|
u_int type;
|
||||||
unsigned char *cp;
|
u_char *cp;
|
||||||
if (buffer_len(&e->input) < 5)
|
if (buffer_len(&e->input) < 5)
|
||||||
return; /* Incomplete message. */
|
return; /* Incomplete message. */
|
||||||
cp = (unsigned char *) buffer_ptr(&e->input);
|
cp = (u_char *) buffer_ptr(&e->input);
|
||||||
msg_len = GET_32BIT(cp);
|
msg_len = GET_32BIT(cp);
|
||||||
if (msg_len > 256 * 1024) {
|
if (msg_len > 256 * 1024) {
|
||||||
shutdown(e->fd, SHUT_RDWR);
|
shutdown(e->fd, SHUT_RDWR);
|
||||||
@ -515,7 +508,7 @@ process_message(SocketEntry *e)
|
|||||||
void
|
void
|
||||||
new_socket(int type, int fd)
|
new_socket(int type, int fd)
|
||||||
{
|
{
|
||||||
unsigned int i, old_alloc;
|
u_int i, old_alloc;
|
||||||
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
|
||||||
error("fcntl O_NONBLOCK: %s", strerror(errno));
|
error("fcntl O_NONBLOCK: %s", strerror(errno));
|
||||||
|
|
||||||
@ -544,17 +537,17 @@ new_socket(int type, int fd)
|
|||||||
buffer_init(&sockets[old_alloc].output);
|
buffer_init(&sockets[old_alloc].output);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
prepare_select(fd_set *readset, fd_set *writeset)
|
prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
u_int i, sz;
|
||||||
for (i = 0; i < sockets_alloc; i++)
|
int n = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < sockets_alloc; i++) {
|
||||||
switch (sockets[i].type) {
|
switch (sockets[i].type) {
|
||||||
case AUTH_SOCKET:
|
case AUTH_SOCKET:
|
||||||
case AUTH_CONNECTION:
|
case AUTH_CONNECTION:
|
||||||
FD_SET(sockets[i].fd, readset);
|
n = MAX(n, sockets[i].fd);
|
||||||
if (buffer_len(&sockets[i].output) > 0)
|
|
||||||
FD_SET(sockets[i].fd, writeset);
|
|
||||||
break;
|
break;
|
||||||
case AUTH_UNUSED:
|
case AUTH_UNUSED:
|
||||||
break;
|
break;
|
||||||
@ -562,12 +555,40 @@ prepare_select(fd_set *readset, fd_set *writeset)
|
|||||||
fatal("Unknown socket type %d", sockets[i].type);
|
fatal("Unknown socket type %d", sockets[i].type);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
|
||||||
|
if (*fdrp == NULL || n > *fdl) {
|
||||||
|
if (*fdrp)
|
||||||
|
xfree(*fdrp);
|
||||||
|
if (*fdwp)
|
||||||
|
xfree(*fdwp);
|
||||||
|
*fdrp = xmalloc(sz);
|
||||||
|
*fdwp = xmalloc(sz);
|
||||||
|
*fdl = n;
|
||||||
|
}
|
||||||
|
memset(*fdrp, 0, sz);
|
||||||
|
memset(*fdwp, 0, sz);
|
||||||
|
|
||||||
|
for (i = 0; i < sockets_alloc; i++) {
|
||||||
|
switch (sockets[i].type) {
|
||||||
|
case AUTH_SOCKET:
|
||||||
|
case AUTH_CONNECTION:
|
||||||
|
FD_SET(sockets[i].fd, *fdrp);
|
||||||
|
if (buffer_len(&sockets[i].output) > 0)
|
||||||
|
FD_SET(sockets[i].fd, *fdwp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
after_select(fd_set *readset, fd_set *writeset)
|
after_select(fd_set *readset, fd_set *writeset)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
u_int i;
|
||||||
int len, sock;
|
int len, sock;
|
||||||
socklen_t slen;
|
socklen_t slen;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
@ -580,7 +601,8 @@ after_select(fd_set *readset, fd_set *writeset)
|
|||||||
case AUTH_SOCKET:
|
case AUTH_SOCKET:
|
||||||
if (FD_ISSET(sockets[i].fd, readset)) {
|
if (FD_ISSET(sockets[i].fd, readset)) {
|
||||||
slen = sizeof(sunaddr);
|
slen = sizeof(sunaddr);
|
||||||
sock = accept(sockets[i].fd, (struct sockaddr *) & sunaddr, &slen);
|
sock = accept(sockets[i].fd,
|
||||||
|
(struct sockaddr *) &sunaddr, &slen);
|
||||||
if (sock < 0) {
|
if (sock < 0) {
|
||||||
perror("accept from AUTH_SOCKET");
|
perror("accept from AUTH_SOCKET");
|
||||||
break;
|
break;
|
||||||
@ -591,8 +613,15 @@ after_select(fd_set *readset, fd_set *writeset)
|
|||||||
case AUTH_CONNECTION:
|
case AUTH_CONNECTION:
|
||||||
if (buffer_len(&sockets[i].output) > 0 &&
|
if (buffer_len(&sockets[i].output) > 0 &&
|
||||||
FD_ISSET(sockets[i].fd, writeset)) {
|
FD_ISSET(sockets[i].fd, writeset)) {
|
||||||
len = write(sockets[i].fd, buffer_ptr(&sockets[i].output),
|
do {
|
||||||
buffer_len(&sockets[i].output));
|
len = write(sockets[i].fd,
|
||||||
|
buffer_ptr(&sockets[i].output),
|
||||||
|
buffer_len(&sockets[i].output));
|
||||||
|
if (len == -1 && (errno == EAGAIN ||
|
||||||
|
errno == EINTR))
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
shutdown(sockets[i].fd, SHUT_RDWR);
|
shutdown(sockets[i].fd, SHUT_RDWR);
|
||||||
close(sockets[i].fd);
|
close(sockets[i].fd);
|
||||||
@ -604,7 +633,13 @@ after_select(fd_set *readset, fd_set *writeset)
|
|||||||
buffer_consume(&sockets[i].output, len);
|
buffer_consume(&sockets[i].output, len);
|
||||||
}
|
}
|
||||||
if (FD_ISSET(sockets[i].fd, readset)) {
|
if (FD_ISSET(sockets[i].fd, readset)) {
|
||||||
len = read(sockets[i].fd, buf, sizeof(buf));
|
do {
|
||||||
|
len = read(sockets[i].fd, buf, sizeof(buf));
|
||||||
|
if (len == -1 && (errno == EAGAIN ||
|
||||||
|
errno == EINTR))
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
} while (1);
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
shutdown(sockets[i].fd, SHUT_RDWR);
|
shutdown(sockets[i].fd, SHUT_RDWR);
|
||||||
close(sockets[i].fd);
|
close(sockets[i].fd);
|
||||||
@ -625,19 +660,24 @@ after_select(fd_set *readset, fd_set *writeset)
|
|||||||
void
|
void
|
||||||
check_parent_exists(int sig)
|
check_parent_exists(int sig)
|
||||||
{
|
{
|
||||||
|
int save_errno = errno;
|
||||||
|
|
||||||
if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
|
if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
|
||||||
/* printf("Parent has died - Authentication agent exiting.\n"); */
|
/* printf("Parent has died - Authentication agent exiting.\n"); */
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
signal(SIGALRM, check_parent_exists);
|
signal(SIGALRM, check_parent_exists);
|
||||||
alarm(10);
|
alarm(10);
|
||||||
|
errno = save_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cleanup_socket(void)
|
cleanup_socket(void)
|
||||||
{
|
{
|
||||||
remove(socket_name);
|
if (socket_name[0])
|
||||||
rmdir(socket_dir);
|
unlink(socket_name);
|
||||||
|
if (socket_dir[0])
|
||||||
|
rmdir(socket_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -648,30 +688,34 @@ cleanup_exit(int i)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
usage()
|
cleanup_handler(int sig)
|
||||||
|
{
|
||||||
|
cleanup_socket();
|
||||||
|
_exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
|
fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
|
||||||
fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n",
|
fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n",
|
||||||
__progname);
|
__progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int ac, char **av)
|
main(int ac, char **av)
|
||||||
{
|
{
|
||||||
fd_set readset, writeset;
|
|
||||||
int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
|
int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
|
||||||
struct sockaddr_un sunaddr;
|
struct sockaddr_un sunaddr;
|
||||||
|
struct rlimit rlim;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
|
char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
|
||||||
|
extern int optind;
|
||||||
|
fd_set *readsetp = NULL, *writesetp = NULL;
|
||||||
|
|
||||||
|
SSLeay_add_all_algorithms();
|
||||||
|
|
||||||
/* check if RSA support exists */
|
|
||||||
if (rsa_alive() == 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
|
|
||||||
__progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
while ((ch = getopt(ac, av, "cks")) != -1) {
|
while ((ch = getopt(ac, av, "cks")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'c':
|
case 'c':
|
||||||
@ -706,14 +750,13 @@ main(int ac, char **av)
|
|||||||
pidstr = getenv(SSH_AGENTPID_ENV_NAME);
|
pidstr = getenv(SSH_AGENTPID_ENV_NAME);
|
||||||
if (pidstr == NULL) {
|
if (pidstr == NULL) {
|
||||||
fprintf(stderr, "%s not set, cannot kill agent\n",
|
fprintf(stderr, "%s not set, cannot kill agent\n",
|
||||||
SSH_AGENTPID_ENV_NAME);
|
SSH_AGENTPID_ENV_NAME);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
pid = atoi(pidstr);
|
pid = atoi(pidstr);
|
||||||
if (pid < 1) { /* XXX PID_MAX check too */
|
if (pid < 1) {
|
||||||
/* Yes, PID_MAX check please */
|
|
||||||
fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
|
fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
|
||||||
SSH_AGENTPID_ENV_NAME, pidstr);
|
SSH_AGENTPID_ENV_NAME, pidstr);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (kill(pid, SIGTERM) == -1) {
|
if (kill(pid, SIGTERM) == -1) {
|
||||||
@ -735,7 +778,7 @@ main(int ac, char **av)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
|
snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
|
||||||
parent_pid);
|
parent_pid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create socket early so it will exist before command gets run from
|
* Create socket early so it will exist before command gets run from
|
||||||
@ -758,6 +801,7 @@ main(int ac, char **av)
|
|||||||
perror("listen");
|
perror("listen");
|
||||||
cleanup_exit(1);
|
cleanup_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fork, and have the parent execute the command, if any, or present
|
* Fork, and have the parent execute the command, if any, or present
|
||||||
* the socket data. The child continues as the authentication agent.
|
* the socket data. The child continues as the authentication agent.
|
||||||
@ -773,9 +817,9 @@ main(int ac, char **av)
|
|||||||
if (ac == 0) {
|
if (ac == 0) {
|
||||||
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
|
format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
|
||||||
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
|
printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
|
||||||
SSH_AUTHSOCKET_ENV_NAME);
|
SSH_AUTHSOCKET_ENV_NAME);
|
||||||
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
|
printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
|
||||||
SSH_AGENTPID_ENV_NAME);
|
SSH_AGENTPID_ENV_NAME);
|
||||||
printf("echo Agent pid %d;\n", pid);
|
printf("echo Agent pid %d;\n", pid);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
@ -792,6 +836,12 @@ main(int ac, char **av)
|
|||||||
close(1);
|
close(1);
|
||||||
close(2);
|
close(2);
|
||||||
|
|
||||||
|
/* deny core dumps, since memory contains unencrypted private keys */
|
||||||
|
rlim.rlim_cur = rlim.rlim_max = 0;
|
||||||
|
if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
|
||||||
|
perror("setrlimit rlimit_core failed");
|
||||||
|
cleanup_exit(1);
|
||||||
|
}
|
||||||
if (setsid() == -1) {
|
if (setsid() == -1) {
|
||||||
perror("setsid");
|
perror("setsid");
|
||||||
cleanup_exit(1);
|
cleanup_exit(1);
|
||||||
@ -808,18 +858,16 @@ main(int ac, char **av)
|
|||||||
idtab_init();
|
idtab_init();
|
||||||
signal(SIGINT, SIG_IGN);
|
signal(SIGINT, SIG_IGN);
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
signal(SIGHUP, cleanup_exit);
|
signal(SIGHUP, cleanup_handler);
|
||||||
signal(SIGTERM, cleanup_exit);
|
signal(SIGTERM, cleanup_handler);
|
||||||
while (1) {
|
while (1) {
|
||||||
FD_ZERO(&readset);
|
prepare_select(&readsetp, &writesetp, &max_fd);
|
||||||
FD_ZERO(&writeset);
|
if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) {
|
||||||
prepare_select(&readset, &writeset);
|
|
||||||
if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) {
|
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
after_select(&readset, &writeset);
|
after_select(readsetp, writesetp);
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
.\" incompatible with the protocol description in the RFC file, it must be
|
.\" incompatible with the protocol description in the RFC file, it must be
|
||||||
.\" called by a name other than "ssh" or "Secure Shell".
|
.\" called by a name other than "ssh" or "Secure Shell".
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
|
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
|
||||||
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
|
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
|
||||||
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
|
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
.\" modification, are permitted provided that the following conditions
|
.\" modification, are permitted provided that the following conditions
|
||||||
@ -34,6 +34,7 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
|
.\" $OpenBSD: ssh.1,v 1.107 2001/04/22 23:58:36 markus Exp $
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd September 25, 1999
|
.Dd September 25, 1999
|
||||||
@ -41,7 +42,7 @@
|
|||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm ssh
|
.Nm ssh
|
||||||
.Nd OpenSSH secure shell client (remote login program)
|
.Nd OpenSSH SSH client (remote login program)
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm ssh
|
.Nm ssh
|
||||||
.Op Fl l Ar login_name
|
.Op Fl l Ar login_name
|
||||||
@ -49,11 +50,12 @@
|
|||||||
.Op Ar command
|
.Op Ar command
|
||||||
.Pp
|
.Pp
|
||||||
.Nm ssh
|
.Nm ssh
|
||||||
.Op Fl afgknqtvxACNPTX246
|
.Op Fl afgknqstvxACNPTX1246
|
||||||
.Op Fl c Ar cipher_spec
|
.Op Fl c Ar cipher_spec
|
||||||
.Op Fl e Ar escape_char
|
.Op Fl e Ar escape_char
|
||||||
.Op Fl i Ar identity_file
|
.Op Fl i Ar identity_file
|
||||||
.Op Fl l Ar login_name
|
.Op Fl l Ar login_name
|
||||||
|
.Op Fl m Ar mac_spec
|
||||||
.Op Fl o Ar option
|
.Op Fl o Ar option
|
||||||
.Op Fl p Ar port
|
.Op Fl p Ar port
|
||||||
.Oo Fl L Xo
|
.Oo Fl L Xo
|
||||||
@ -76,7 +78,7 @@
|
|||||||
.Op Ar command
|
.Op Ar command
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
(Secure Shell) is a program for logging into a remote machine and for
|
(SSH client) is a program for logging into a remote machine and for
|
||||||
executing commands on a remote machine.
|
executing commands on a remote machine.
|
||||||
It is intended to replace
|
It is intended to replace
|
||||||
rlogin and rsh, and provide secure encrypted communications between
|
rlogin and rsh, and provide secure encrypted communications between
|
||||||
@ -110,7 +112,7 @@ permitted to log in.
|
|||||||
This form of authentication alone is normally not
|
This form of authentication alone is normally not
|
||||||
allowed by the server because it is not secure.
|
allowed by the server because it is not secure.
|
||||||
.Pp
|
.Pp
|
||||||
The second (and primary) authentication method is the
|
The second authentication method is the
|
||||||
.Pa rhosts
|
.Pa rhosts
|
||||||
or
|
or
|
||||||
.Pa hosts.equiv
|
.Pa hosts.equiv
|
||||||
@ -205,15 +207,22 @@ the password cannot be seen by someone listening on the network.
|
|||||||
.Ss SSH protocol version 2
|
.Ss SSH protocol version 2
|
||||||
.Pp
|
.Pp
|
||||||
When a user connects using the protocol version 2
|
When a user connects using the protocol version 2
|
||||||
different authentication methods are available:
|
different authentication methods are available.
|
||||||
At first, the client attempts to authenticate using the public key method.
|
Using the default values for
|
||||||
If this method fails password authentication is tried.
|
.Cm PreferredAuthentications ,
|
||||||
|
the client will try to authenticate first using the public key method;
|
||||||
|
if this method fails password authentication is attempted,
|
||||||
|
and finally if this method fails keyboard-interactive authentication
|
||||||
|
is attempted.
|
||||||
|
If this method fails password authentication is
|
||||||
|
tried.
|
||||||
.Pp
|
.Pp
|
||||||
The public key method is similar to RSA authentication described
|
The public key method is similar to RSA authentication described
|
||||||
in the previous section except that the DSA algorithm is used
|
in the previous section and allows the RSA or DSA algorithm to be used:
|
||||||
instead of the patented RSA algorithm.
|
The client uses his private key,
|
||||||
The client uses his private DSA key
|
|
||||||
.Pa $HOME/.ssh/id_dsa
|
.Pa $HOME/.ssh/id_dsa
|
||||||
|
or
|
||||||
|
.Pa $HOME/.ssh/id_rsa ,
|
||||||
to sign the session identifier and sends the result to the server.
|
to sign the session identifier and sends the result to the server.
|
||||||
The server checks whether the matching public key is listed in
|
The server checks whether the matching public key is listed in
|
||||||
.Pa $HOME/.ssh/authorized_keys2
|
.Pa $HOME/.ssh/authorized_keys2
|
||||||
@ -223,12 +232,14 @@ and is only known to the client and the server.
|
|||||||
.Pp
|
.Pp
|
||||||
If public key authentication fails or is not available a password
|
If public key authentication fails or is not available a password
|
||||||
can be sent encrypted to the remote host for proving the user's identity.
|
can be sent encrypted to the remote host for proving the user's identity.
|
||||||
This protocol 2 implementation does not yet support Kerberos or
|
.Pp
|
||||||
OPIE authentication.
|
Additionally,
|
||||||
|
.Nm
|
||||||
|
supports hostbased or challenge response authentication.
|
||||||
.Pp
|
.Pp
|
||||||
Protocol 2 provides additional mechanisms for confidentiality
|
Protocol 2 provides additional mechanisms for confidentiality
|
||||||
(the traffic is encrypted using 3DES, Blowfish, CAST128 or Arcfour)
|
(the traffic is encrypted using 3DES, Blowfish, CAST128 or Arcfour)
|
||||||
and integrity (hmac-sha1, hmac-md5).
|
and integrity (hmac-md5, hmac-sha1).
|
||||||
Note that protocol 1 lacks a strong mechanism for ensuring the
|
Note that protocol 1 lacks a strong mechanism for ensuring the
|
||||||
integrity of the connection.
|
integrity of the connection.
|
||||||
.Pp
|
.Pp
|
||||||
@ -241,30 +252,7 @@ All communication with
|
|||||||
the remote command or shell will be automatically encrypted.
|
the remote command or shell will be automatically encrypted.
|
||||||
.Pp
|
.Pp
|
||||||
If a pseudo-terminal has been allocated (normal login session), the
|
If a pseudo-terminal has been allocated (normal login session), the
|
||||||
user can disconnect with
|
user may use the escape characters noted below.
|
||||||
.Ic ~. ,
|
|
||||||
and suspend
|
|
||||||
.Nm
|
|
||||||
with
|
|
||||||
.Ic ~^Z .
|
|
||||||
All forwarded connections can be listed with
|
|
||||||
.Ic ~#
|
|
||||||
and if
|
|
||||||
the session blocks waiting for forwarded X11 or TCP/IP
|
|
||||||
connections to terminate, it can be backgrounded with
|
|
||||||
.Ic ~&
|
|
||||||
(this should not be used while the user shell is active, as it can cause the
|
|
||||||
shell to hang).
|
|
||||||
All available escapes can be listed with
|
|
||||||
.Ic ~? .
|
|
||||||
.Pp
|
|
||||||
A single tilde character can be sent as
|
|
||||||
.Ic ~~
|
|
||||||
(or by following the tilde by a character other than those described above).
|
|
||||||
The escape character must always follow a newline to be interpreted as
|
|
||||||
special.
|
|
||||||
The escape character can be changed in configuration files
|
|
||||||
or on the command line.
|
|
||||||
.Pp
|
.Pp
|
||||||
If no pseudo tty has been allocated, the
|
If no pseudo tty has been allocated, the
|
||||||
session is transparent and can be used to reliably transfer binary
|
session is transparent and can be used to reliably transfer binary
|
||||||
@ -273,12 +261,48 @@ On most systems, setting the escape character to
|
|||||||
.Dq none
|
.Dq none
|
||||||
will also make the session transparent even if a tty is used.
|
will also make the session transparent even if a tty is used.
|
||||||
.Pp
|
.Pp
|
||||||
The session terminates when the command or shell in on the remote
|
The session terminates when the command or shell on the remote
|
||||||
machine exists and all X11 and TCP/IP connections have been closed.
|
machine exits and all X11 and TCP/IP connections have been closed.
|
||||||
The exit status of the remote program is returned as the exit status
|
The exit status of the remote program is returned as the exit status
|
||||||
of
|
of
|
||||||
.Nm ssh .
|
.Nm ssh .
|
||||||
.Pp
|
.Pp
|
||||||
|
.Ss Escape Characters
|
||||||
|
.Pp
|
||||||
|
When a pseudo terminal has been requested, ssh supports a number of functions
|
||||||
|
through the use of an escape character.
|
||||||
|
.Pp
|
||||||
|
A single tilde character can be sent as
|
||||||
|
.Ic ~~
|
||||||
|
(or by following the tilde by a character other than those described above).
|
||||||
|
The escape character must always follow a newline to be interpreted as
|
||||||
|
special.
|
||||||
|
The escape character can be changed in configuration files using the
|
||||||
|
.Cm EscapeChar
|
||||||
|
configuration directive or on the command line by the
|
||||||
|
.Fl e
|
||||||
|
option.
|
||||||
|
.Pp
|
||||||
|
The supported escapes (assuming the default
|
||||||
|
.Ql ~ )
|
||||||
|
are:
|
||||||
|
.Bl -tag -width Ds
|
||||||
|
.It Cm ~.
|
||||||
|
Disconnect
|
||||||
|
.It Cm ~^Z
|
||||||
|
Background ssh
|
||||||
|
.It Cm ~#
|
||||||
|
List forwarded connections
|
||||||
|
.It Cm ~&
|
||||||
|
Background ssh at logout when waiting for forwarded connection / X11 sessions
|
||||||
|
to terminate (protocol version 1 only)
|
||||||
|
.It Cm ~?
|
||||||
|
Display a list of escape characters
|
||||||
|
.It Cm ~R
|
||||||
|
Request rekeying of the connection (only useful for SSH protocol version 2
|
||||||
|
and if the peer supports it)
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
.Ss X11 and TCP forwarding
|
.Ss X11 and TCP forwarding
|
||||||
.Pp
|
.Pp
|
||||||
If the user is using X11 (the
|
If the user is using X11 (the
|
||||||
@ -323,7 +347,7 @@ command line or in a configuration file.
|
|||||||
Forwarding of arbitrary TCP/IP connections over the secure channel can
|
Forwarding of arbitrary TCP/IP connections over the secure channel can
|
||||||
be specified either on command line or in a configuration file.
|
be specified either on command line or in a configuration file.
|
||||||
One possible application of TCP/IP forwarding is a secure connection to an
|
One possible application of TCP/IP forwarding is a secure connection to an
|
||||||
electronic purse; another is going trough firewalls.
|
electronic purse; another is going through firewalls.
|
||||||
.Pp
|
.Pp
|
||||||
.Ss Server authentication
|
.Ss Server authentication
|
||||||
.Pp
|
.Pp
|
||||||
@ -333,7 +357,7 @@ identifications for all hosts it has ever been used with.
|
|||||||
RSA host keys are stored in
|
RSA host keys are stored in
|
||||||
.Pa $HOME/.ssh/known_hosts
|
.Pa $HOME/.ssh/known_hosts
|
||||||
and
|
and
|
||||||
DSA host keys are stored in
|
host keys used in the protocol version 2 are stored in
|
||||||
.Pa $HOME/.ssh/known_hosts2
|
.Pa $HOME/.ssh/known_hosts2
|
||||||
in the user's home directory.
|
in the user's home directory.
|
||||||
Additionally, the files
|
Additionally, the files
|
||||||
@ -354,7 +378,8 @@ The
|
|||||||
.Cm StrictHostKeyChecking
|
.Cm StrictHostKeyChecking
|
||||||
option (see below) can be used to prevent logins to machines whose
|
option (see below) can be used to prevent logins to machines whose
|
||||||
host key is not known or has changed.
|
host key is not known or has changed.
|
||||||
.Sh OPTIONS
|
.Pp
|
||||||
|
The options are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Fl a
|
.It Fl a
|
||||||
Disables forwarding of the authentication agent connection.
|
Disables forwarding of the authentication agent connection.
|
||||||
@ -375,11 +400,12 @@ cipher which is no longer fully supported in
|
|||||||
.Ar blowfish
|
.Ar blowfish
|
||||||
is a fast block cipher, it appears very secure and is much faster than
|
is a fast block cipher, it appears very secure and is much faster than
|
||||||
.Ar 3des .
|
.Ar 3des .
|
||||||
.It Fl c Ar "3des-cbc,blowfish-cbc,arcfour,cast128-cbc"
|
.It Fl c Ar cipher_spec
|
||||||
Additionally, for protocol version 2 a comma-separated list of ciphers can
|
Additionally, for protocol version 2 a comma-separated list of ciphers can
|
||||||
be specified in order of preference.
|
be specified in order of preference.
|
||||||
Protocol version 2 supports 3DES, Blowfish, and CAST128 in CBC mode
|
See
|
||||||
and Arcfour.
|
.Cm Ciphers
|
||||||
|
for more information.
|
||||||
.It Fl e Ar ch|^ch|none
|
.It Fl e Ar ch|^ch|none
|
||||||
Sets the escape character for sessions with a pty (default:
|
Sets the escape character for sessions with a pty (default:
|
||||||
.Ql ~ ) .
|
.Ql ~ ) .
|
||||||
@ -409,7 +435,7 @@ something like
|
|||||||
Allows remote hosts to connect to local forwarded ports.
|
Allows remote hosts to connect to local forwarded ports.
|
||||||
.It Fl i Ar identity_file
|
.It Fl i Ar identity_file
|
||||||
Selects the file from which the identity (private key) for
|
Selects the file from which the identity (private key) for
|
||||||
RSA authentication is read.
|
RSA or DSA authentication is read.
|
||||||
Default is
|
Default is
|
||||||
.Pa $HOME/.ssh/identity
|
.Pa $HOME/.ssh/identity
|
||||||
in the user's home directory.
|
in the user's home directory.
|
||||||
@ -425,6 +451,13 @@ This may also be specified on a per-host basis in the configuration file.
|
|||||||
.It Fl l Ar login_name
|
.It Fl l Ar login_name
|
||||||
Specifies the user to log in as on the remote machine.
|
Specifies the user to log in as on the remote machine.
|
||||||
This also may be specified on a per-host basis in the configuration file.
|
This also may be specified on a per-host basis in the configuration file.
|
||||||
|
.It Fl m Ar mac_spec
|
||||||
|
Additionally, for protocol version 2 a comma-separated list of MAC
|
||||||
|
(message authentication code) algorithms can
|
||||||
|
be specified in order of preference.
|
||||||
|
See the
|
||||||
|
.Cm MACs
|
||||||
|
keyword for more information.
|
||||||
.It Fl n
|
.It Fl n
|
||||||
Redirects stdin from
|
Redirects stdin from
|
||||||
.Pa /dev/null
|
.Pa /dev/null
|
||||||
@ -447,7 +480,7 @@ needs to ask for a password or passphrase; see also the
|
|||||||
option.)
|
option.)
|
||||||
.It Fl N
|
.It Fl N
|
||||||
Do not execute a remote command.
|
Do not execute a remote command.
|
||||||
This is usefull if you just want to forward ports
|
This is useful if you just want to forward ports
|
||||||
(protocol version 2 only).
|
(protocol version 2 only).
|
||||||
.It Fl o Ar option
|
.It Fl o Ar option
|
||||||
Can be used to give options in the format used in the config file.
|
Can be used to give options in the format used in the config file.
|
||||||
@ -465,18 +498,28 @@ not permit connections from privileged ports.
|
|||||||
Note that this option turns off
|
Note that this option turns off
|
||||||
.Cm RhostsAuthentication
|
.Cm RhostsAuthentication
|
||||||
and
|
and
|
||||||
.Cm RhostsRSAAuthentication .
|
.Cm RhostsRSAAuthentication
|
||||||
|
for older servers.
|
||||||
.It Fl q
|
.It Fl q
|
||||||
Quiet mode.
|
Quiet mode.
|
||||||
Causes all warning and diagnostic messages to be suppressed.
|
Causes all warning and diagnostic messages to be suppressed.
|
||||||
Only fatal errors are displayed.
|
Only fatal errors are displayed.
|
||||||
|
.It Fl s
|
||||||
|
May be used to request invocation of a subsystem on the remote system. Subsystems are a feature of the SSH2 protocol which facilitate the use
|
||||||
|
of SSH as a secure transport for other application (eg. sftp). The
|
||||||
|
subsystem is specified as the remote command.
|
||||||
.It Fl t
|
.It Fl t
|
||||||
Force pseudo-tty allocation.
|
Force pseudo-tty allocation.
|
||||||
This can be used to execute arbitrary
|
This can be used to execute arbitrary
|
||||||
screen-based programs on a remote machine, which can be very useful,
|
screen-based programs on a remote machine, which can be very useful,
|
||||||
e.g., when implementing menu services.
|
e.g., when implementing menu services.
|
||||||
|
Multiple
|
||||||
|
.Fl t
|
||||||
|
options force tty allocation, even if
|
||||||
|
.Nm
|
||||||
|
has no local tty.
|
||||||
.It Fl T
|
.It Fl T
|
||||||
Disable pseudo-tty allocation (protocol version 2 only).
|
Disable pseudo-tty allocation.
|
||||||
.It Fl v
|
.It Fl v
|
||||||
Verbose mode.
|
Verbose mode.
|
||||||
Causes
|
Causes
|
||||||
@ -484,10 +527,9 @@ Causes
|
|||||||
to print debugging messages about its progress.
|
to print debugging messages about its progress.
|
||||||
This is helpful in
|
This is helpful in
|
||||||
debugging connection, authentication, and configuration problems.
|
debugging connection, authentication, and configuration problems.
|
||||||
The verbose mode is also used to display
|
Multiple
|
||||||
.Xr skey 1
|
.Fl v
|
||||||
challenges, if the user entered "s/key" as password.
|
options increases the verbosity.
|
||||||
Multiple -v options increases the verbosity.
|
|
||||||
Maximum is 3.
|
Maximum is 3.
|
||||||
.It Fl x
|
.It Fl x
|
||||||
Disables X11 forwarding.
|
Disables X11 forwarding.
|
||||||
@ -541,6 +583,12 @@ from the local machine.
|
|||||||
Port forwardings can also be specified in the configuration file.
|
Port forwardings can also be specified in the configuration file.
|
||||||
Privileged ports can be forwarded only when
|
Privileged ports can be forwarded only when
|
||||||
logging in as root on the remote machine.
|
logging in as root on the remote machine.
|
||||||
|
IPv6 addresses can be specified with an alternative syntax:
|
||||||
|
.Ar port/host/hostport
|
||||||
|
.It Fl 1
|
||||||
|
Forces
|
||||||
|
.Nm
|
||||||
|
to try protocol version 1 only.
|
||||||
.It Fl 2
|
.It Fl 2
|
||||||
Forces
|
Forces
|
||||||
.Nm
|
.Nm
|
||||||
@ -609,6 +657,7 @@ The argument to this keyword must be
|
|||||||
.Dq yes
|
.Dq yes
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
This option applies to protocol version 1 only.
|
||||||
.It Cm BatchMode
|
.It Cm BatchMode
|
||||||
If set to
|
If set to
|
||||||
.Dq yes ,
|
.Dq yes ,
|
||||||
@ -619,16 +668,20 @@ The argument must be
|
|||||||
.Dq yes
|
.Dq yes
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
.It Cm CheckHostIP
|
.It Cm CheckHostIP
|
||||||
If this flag is set to
|
If this flag is set to
|
||||||
.Dq yes ,
|
.Dq yes ,
|
||||||
ssh will additionally check the host ip address in the
|
ssh will additionally check the host IP address in the
|
||||||
.Pa known_hosts
|
.Pa known_hosts
|
||||||
file.
|
file.
|
||||||
This allows ssh to detect if a host key changed due to DNS spoofing.
|
This allows ssh to detect if a host key changed due to DNS spoofing.
|
||||||
If the option is set to
|
If the option is set to
|
||||||
.Dq no ,
|
.Dq no ,
|
||||||
the check will not be executed.
|
the check will not be executed.
|
||||||
|
The default is
|
||||||
|
.Dq yes .
|
||||||
.It Cm Cipher
|
.It Cm Cipher
|
||||||
Specifies the cipher to use for encrypting the session
|
Specifies the cipher to use for encrypting the session
|
||||||
in protocol version 1.
|
in protocol version 1.
|
||||||
@ -644,33 +697,32 @@ Specifies the ciphers allowed for protocol version 2
|
|||||||
in order of preference.
|
in order of preference.
|
||||||
Multiple ciphers must be comma-separated.
|
Multiple ciphers must be comma-separated.
|
||||||
The default is
|
The default is
|
||||||
.Dq 3des-cbc,blowfish-cbc,cast128-cbc,arcfour .
|
.Pp
|
||||||
|
.Bd -literal
|
||||||
|
``aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,
|
||||||
|
aes192-cbc,aes256-cbc''
|
||||||
|
.Ed
|
||||||
.It Cm Compression
|
.It Cm Compression
|
||||||
Specifies whether to use compression.
|
Specifies whether to use compression.
|
||||||
The argument must be
|
The argument must be
|
||||||
.Dq yes
|
.Dq yes
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
.It Cm CompressionLevel
|
.It Cm CompressionLevel
|
||||||
Specifies the compression level to use if compression is enable.
|
Specifies the compression level to use if compression is enabled.
|
||||||
The argument must be an integer from 1 (fast) to 9 (slow, best).
|
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 default level is 6, which is good for most applications.
|
||||||
The meaning of the values is the same as in
|
The meaning of the values is the same as in
|
||||||
.Xr gzip 1 .
|
.Xr gzip 1 .
|
||||||
|
Note that this option applies to protocol version 1 only.
|
||||||
.It Cm ConnectionAttempts
|
.It Cm ConnectionAttempts
|
||||||
Specifies the number of tries (one per second) to make before falling
|
Specifies the number of tries (one per second) to make before falling
|
||||||
back to rsh or exiting.
|
back to rsh or exiting.
|
||||||
The argument must be an integer.
|
The argument must be an integer.
|
||||||
This may be useful in scripts if the connection sometimes fails.
|
This may be useful in scripts if the connection sometimes fails.
|
||||||
.It Cm DSAAuthentication
|
The default is 4.
|
||||||
Specifies whether to try DSA authentication.
|
|
||||||
The argument to this keyword must be
|
|
||||||
.Dq yes
|
|
||||||
or
|
|
||||||
.Dq no .
|
|
||||||
DSA authentication will only be
|
|
||||||
attempted if a DSA identity file exists.
|
|
||||||
Note that this option applies to protocol version 2 only.
|
|
||||||
.It Cm EscapeChar
|
.It Cm EscapeChar
|
||||||
Sets the escape character (default:
|
Sets the escape character (default:
|
||||||
.Ql ~ ) .
|
.Ql ~ ) .
|
||||||
@ -696,6 +748,8 @@ The argument must be
|
|||||||
.Dq yes
|
.Dq yes
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
.It Cm ForwardAgent
|
.It Cm ForwardAgent
|
||||||
Specifies whether the connection to the authentication agent (if any)
|
Specifies whether the connection to the authentication agent (if any)
|
||||||
will be forwarded to the remote machine.
|
will be forwarded to the remote machine.
|
||||||
@ -726,8 +780,37 @@ or
|
|||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
.It Cm GlobalKnownHostsFile
|
.It Cm GlobalKnownHostsFile
|
||||||
Specifies a file to use instead of
|
Specifies a file to use for the protocol version 1 global
|
||||||
|
host key database instead of
|
||||||
.Pa /etc/ssh/ssh_known_hosts .
|
.Pa /etc/ssh/ssh_known_hosts .
|
||||||
|
.It Cm GlobalKnownHostsFile2
|
||||||
|
Specifies a file to use for the protocol version 2 global
|
||||||
|
host key database instead of
|
||||||
|
.Pa /etc/ssh/ssh_known_hosts2 .
|
||||||
|
.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 yes .
|
||||||
|
This option applies to protocol version 2 only and
|
||||||
|
is similar to
|
||||||
|
.Cm RhostsRSAAuthentication .
|
||||||
|
.It Cm HostKeyAlgorithms
|
||||||
|
Specfies 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 if you have multiple servers running on a single host.
|
||||||
|
>>>>>>> 1.1.1.7
|
||||||
.It Cm HostName
|
.It Cm HostName
|
||||||
Specifies the real host name to log into.
|
Specifies the real host name to log into.
|
||||||
This can be used to specify nicknames or abbreviations for hosts.
|
This can be used to specify nicknames or abbreviations for hosts.
|
||||||
@ -736,7 +819,7 @@ Numeric IP addresses are also permitted (both on the command line and in
|
|||||||
.Cm HostName
|
.Cm HostName
|
||||||
specifications).
|
specifications).
|
||||||
.It Cm IdentityFile
|
.It Cm IdentityFile
|
||||||
Specifies the file from which the user's RSA authentication identity
|
Specifies the file from which the user's RSA or DSA authentication identity
|
||||||
is read (default
|
is read (default
|
||||||
.Pa $HOME/.ssh/identity
|
.Pa $HOME/.ssh/identity
|
||||||
in the user's home directory).
|
in the user's home directory).
|
||||||
@ -747,16 +830,6 @@ syntax to refer to a user's home directory.
|
|||||||
It is possible to have
|
It is possible to have
|
||||||
multiple identity files specified in configuration files; all these
|
multiple identity files specified in configuration files; all these
|
||||||
identities will be tried in sequence.
|
identities will be tried in sequence.
|
||||||
.It Cm IdentityFile2
|
|
||||||
Specifies the file from which the user's DSA authentication identity
|
|
||||||
is read (default
|
|
||||||
.Pa $HOME/.ssh/id_dsa
|
|
||||||
in the user's home directory).
|
|
||||||
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
|
.It Cm KeepAlive
|
||||||
Specifies whether the system should send keepalive messages to the
|
Specifies whether the system should send keepalive messages to the
|
||||||
other side.
|
other side.
|
||||||
@ -802,6 +875,18 @@ Gives the verbosity level that is used when logging messages from
|
|||||||
The possible values are:
|
The possible values are:
|
||||||
QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG.
|
QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG.
|
||||||
The default is INFO.
|
The default is INFO.
|
||||||
|
.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
|
||||||
|
.Pp
|
||||||
|
.Bd -literal
|
||||||
|
``hmac-md5,hmac-sha1,hmac-ripemd160,hmac-ripemd160@openssh.com,
|
||||||
|
hmac-sha1-96,hmac-md5-96''
|
||||||
|
.Ed
|
||||||
.It Cm NumberOfPasswordPrompts
|
.It Cm NumberOfPasswordPrompts
|
||||||
Specifies the number of password prompts before giving up.
|
Specifies the number of password prompts before giving up.
|
||||||
The argument to this keyword must be an integer.
|
The argument to this keyword must be an integer.
|
||||||
@ -812,10 +897,19 @@ The argument to this keyword must be
|
|||||||
.Dq yes
|
.Dq yes
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
Note that this option applies to both protocol version 1 and 2.
|
The default is
|
||||||
|
.Dq yes .
|
||||||
.It Cm Port
|
.It Cm Port
|
||||||
Specifies the port number to connect on the remote host.
|
Specifies the port number to connect on the remote host.
|
||||||
Default is 22.
|
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 publickey, password, keyboard-interactive
|
||||||
.It Cm Protocol
|
.It Cm Protocol
|
||||||
Specifies the protocol versions
|
Specifies the protocol versions
|
||||||
.Nm
|
.Nm
|
||||||
@ -826,11 +920,11 @@ and
|
|||||||
.Dq 2 .
|
.Dq 2 .
|
||||||
Multiple versions must be comma-separated.
|
Multiple versions must be comma-separated.
|
||||||
The default is
|
The default is
|
||||||
.Dq 1,2 .
|
.Dq 2,1 .
|
||||||
This means that
|
This means that
|
||||||
.Nm
|
.Nm
|
||||||
tries version 1 and falls back to version 2
|
tries version 2 and falls back to version 1
|
||||||
if version 1 is not available.
|
if version 2 is not available.
|
||||||
.It Cm ProxyCommand
|
.It Cm ProxyCommand
|
||||||
Specifies the command to use to connect to the server.
|
Specifies the command to use to connect to the server.
|
||||||
The command
|
The command
|
||||||
@ -856,6 +950,15 @@ Note that
|
|||||||
.Cm CheckHostIP
|
.Cm CheckHostIP
|
||||||
is not available for connects with a proxy command.
|
is not available for connects with a proxy command.
|
||||||
.Pp
|
.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
|
.It Cm RemoteForward
|
||||||
Specifies that a TCP/IP port on the remote machine be forwarded over
|
Specifies that a TCP/IP port on the remote machine be forwarded over
|
||||||
the secure channel to given host:port from the local machine.
|
the secure channel to given host:port from the local machine.
|
||||||
@ -873,19 +976,25 @@ Disabling rhosts authentication may reduce
|
|||||||
authentication time on slow connections when rhosts authentication is
|
authentication time on slow connections when rhosts authentication is
|
||||||
not used.
|
not used.
|
||||||
Most servers do not permit RhostsAuthentication because it
|
Most servers do not permit RhostsAuthentication because it
|
||||||
is not secure (see RhostsRSAAuthentication).
|
is not secure (see
|
||||||
|
.Cm RhostsRSAAuthentication ).
|
||||||
The argument to this keyword must be
|
The argument to this keyword must be
|
||||||
.Dq yes
|
.Dq yes
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
The default is
|
||||||
|
.Dq yes .
|
||||||
|
This option applies to protocol version 1 only.
|
||||||
.It Cm RhostsRSAAuthentication
|
.It Cm RhostsRSAAuthentication
|
||||||
Specifies whether to try rhosts based authentication with RSA host
|
Specifies whether to try rhosts based authentication with RSA host
|
||||||
authentication.
|
authentication.
|
||||||
This is the primary authentication method for most sites.
|
|
||||||
The argument must be
|
The argument must be
|
||||||
.Dq yes
|
.Dq yes
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
The default is
|
||||||
|
.Dq yes .
|
||||||
|
This option applies to protocol version 1 only.
|
||||||
.It Cm RSAAuthentication
|
.It Cm RSAAuthentication
|
||||||
Specifies whether to try RSA authentication.
|
Specifies whether to try RSA authentication.
|
||||||
The argument to this keyword must be
|
The argument to this keyword must be
|
||||||
@ -895,9 +1004,12 @@ or
|
|||||||
RSA authentication will only be
|
RSA authentication will only be
|
||||||
attempted if the identity file exists, or an authentication agent is
|
attempted if the identity file exists, or an authentication agent is
|
||||||
running.
|
running.
|
||||||
|
The default is
|
||||||
|
.Dq yes .
|
||||||
Note that this option applies to protocol version 1 only.
|
Note that this option applies to protocol version 1 only.
|
||||||
.It Cm SkeyAuthentication
|
.It Cm ChallengeResponseAuthentication
|
||||||
Specifies whether to use
|
Specifies whether to use challenge response authentication.
|
||||||
|
Currently there is only support for
|
||||||
.Xr skey 1
|
.Xr skey 1
|
||||||
authentication.
|
authentication.
|
||||||
The argument to this keyword must be
|
The argument to this keyword must be
|
||||||
@ -914,24 +1026,37 @@ will never automatically add host keys to the
|
|||||||
.Pa $HOME/.ssh/known_hosts
|
.Pa $HOME/.ssh/known_hosts
|
||||||
and
|
and
|
||||||
.Pa $HOME/.ssh/known_hosts2
|
.Pa $HOME/.ssh/known_hosts2
|
||||||
files, and refuses to connect hosts whose host key has changed.
|
files, and refuses to connect to hosts whose host key has changed.
|
||||||
This provides maximum protection against trojan horse attacks.
|
This provides maximum protection against trojan horse attacks.
|
||||||
However, it can be somewhat annoying if you don't have good
|
However, it can be somewhat annoying if you don't have good
|
||||||
.Pa /etc/ssh/ssh_known_hosts
|
.Pa /etc/ssh/ssh_known_hosts
|
||||||
and
|
and
|
||||||
.Pa /etc/ssh/ssh_known_hosts2
|
.Pa /etc/ssh/ssh_known_hosts2
|
||||||
files installed and frequently
|
files installed and frequently
|
||||||
connect new hosts.
|
connect to new hosts.
|
||||||
Basically this option forces the user to manually
|
This option forces the user to manually
|
||||||
add any new hosts.
|
add all new hosts.
|
||||||
Normally this option is disabled, and new hosts
|
If this flag is set to
|
||||||
will automatically be added to the known host files.
|
.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
|
The host keys of
|
||||||
known hosts will be verified automatically in either case.
|
known hosts will be verified automatically in all cases.
|
||||||
The argument must be
|
The argument must be
|
||||||
.Dq yes
|
.Dq yes ,
|
||||||
|
.Dq no
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq ask .
|
||||||
|
The default is
|
||||||
|
.Dq ask .
|
||||||
.It Cm UsePrivilegedPort
|
.It Cm UsePrivilegedPort
|
||||||
Specifies whether to use a privileged port for outgoing connections.
|
Specifies whether to use a privileged port for outgoing connections.
|
||||||
The argument must be
|
The argument must be
|
||||||
@ -939,21 +1064,27 @@ The argument must be
|
|||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
The default is
|
The default is
|
||||||
.Dq yes .
|
.Dq no .
|
||||||
Note that setting this option to
|
Note that you need to set this option to
|
||||||
.Dq no
|
.Dq yes
|
||||||
turns off
|
if you want to use
|
||||||
.Cm RhostsAuthentication
|
.Cm RhostsAuthentication
|
||||||
and
|
and
|
||||||
.Cm RhostsRSAAuthentication .
|
.Cm RhostsRSAAuthentication
|
||||||
|
with older servers.
|
||||||
.It Cm User
|
.It Cm User
|
||||||
Specifies the user to log in as.
|
Specifies the user to log in as.
|
||||||
This can be useful if you have a different user name on different machines.
|
This can be useful if you have a different user name on different machines.
|
||||||
This saves the trouble of
|
This saves the trouble of
|
||||||
having to remember to give the user name on the command line.
|
having to remember to give the user name on the command line.
|
||||||
.It Cm UserKnownHostsFile
|
.It Cm UserKnownHostsFile
|
||||||
Specifies a file to use instead of
|
Specifies a file to use for the protocol version 1 user
|
||||||
|
host key database instead of
|
||||||
.Pa $HOME/.ssh/known_hosts .
|
.Pa $HOME/.ssh/known_hosts .
|
||||||
|
.It Cm UserKnownHostsFile2
|
||||||
|
Specifies a file to use for the protocol version 2 user
|
||||||
|
host key database instead of
|
||||||
|
.Pa $HOME/.ssh/known_hosts2 .
|
||||||
.It Cm UseRsh
|
.It Cm UseRsh
|
||||||
Specifies that rlogin/rsh should be used for this host.
|
Specifies that rlogin/rsh should be used for this host.
|
||||||
It is possible that the host does not at all support the
|
It is possible that the host does not at all support the
|
||||||
@ -994,7 +1125,9 @@ the host where the shell runs, and n is an integer \*(>= 1.
|
|||||||
.Nm
|
.Nm
|
||||||
uses this special value to forward X11 connections over the secure
|
uses this special value to forward X11 connections over the secure
|
||||||
channel.
|
channel.
|
||||||
The user should normally not set DISPLAY explicitly, as that
|
The user should normally not set
|
||||||
|
.Ev DISPLAY
|
||||||
|
explicitly, as that
|
||||||
will render the X11 connection insecure (and will require the user to
|
will render the X11 connection insecure (and will require the user to
|
||||||
manually copy any required authorization cookies).
|
manually copy any required authorization cookies).
|
||||||
.It Ev HOME
|
.It Ev HOME
|
||||||
@ -1018,6 +1151,10 @@ Identifies the client end of the connection.
|
|||||||
The variable contains
|
The variable contains
|
||||||
three space-separated values: client ip-address, client port number,
|
three space-separated values: client ip-address, client port number,
|
||||||
and server port number.
|
and server port number.
|
||||||
|
.It Ev SSH_ORIGINAL_COMMAND
|
||||||
|
The variable contains the original command line if a forced command
|
||||||
|
is executed.
|
||||||
|
It can be used to extract the original arguments.
|
||||||
.It Ev SSH_TTY
|
.It Ev SSH_TTY
|
||||||
This is set to the name of the tty (path to the device) associated
|
This is set to the name of the tty (path to the device) associated
|
||||||
with the current shell or command.
|
with the current shell or command.
|
||||||
@ -1040,14 +1177,18 @@ and adds lines of the format
|
|||||||
to the environment.
|
to the environment.
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Pa $HOME/.ssh/known_hosts
|
.It Pa $HOME/.ssh/known_hosts, $HOME/.ssh/known_hosts2
|
||||||
Records host keys for all hosts the user has logged into (that are not
|
Records host keys for all hosts the user has logged into (that are not
|
||||||
in
|
in
|
||||||
.Pa /etc/ssh/ssh_known_hosts ) .
|
.Pa /etc/ssh/ssh_known_hosts
|
||||||
|
for protocol version 1 or
|
||||||
|
.Pa /etc/ssh/ssh_known_hosts2
|
||||||
|
for protocol version 2).
|
||||||
See
|
See
|
||||||
.Xr sshd 8 .
|
.Xr sshd 8 .
|
||||||
.It Pa $HOME/.ssh/identity, $HOME/.ssh/id_dsa
|
.It Pa $HOME/.ssh/identity, $HOME/.ssh/id_dsa, $HOME/.ssh/id_rsa
|
||||||
Contains the RSA and the DSA authentication identity of the user.
|
Contains the authentication identity of the user.
|
||||||
|
They are for protocol 1 RSA, protocol 2 DSA, and protocol 2 RSA, respectively.
|
||||||
These files
|
These files
|
||||||
contain sensitive data and should be readable by the user but not
|
contain sensitive data and should be readable by the user but not
|
||||||
accessible by others (read/write/execute).
|
accessible by others (read/write/execute).
|
||||||
@ -1057,7 +1198,7 @@ ignores a private key file if it is accessible by others.
|
|||||||
It is possible to specify a passphrase when
|
It is possible to specify a passphrase when
|
||||||
generating the key; the passphrase will be used to encrypt the
|
generating the key; the passphrase will be used to encrypt the
|
||||||
sensitive part of this file using 3DES.
|
sensitive part of this file using 3DES.
|
||||||
.It Pa $HOME/.ssh/identity.pub, $HOME/.ssh/id_dsa.pub
|
.It Pa $HOME/.ssh/identity.pub, $HOME/.ssh/id_dsa.pub, $HOME/.ssh/id_rsa.pub
|
||||||
Contains the public key for authentication (public part of the
|
Contains the public key for authentication (public part of the
|
||||||
identity file in human-readable form).
|
identity file in human-readable form).
|
||||||
The contents of the
|
The contents of the
|
||||||
@ -1065,13 +1206,15 @@ The contents of the
|
|||||||
file should be added to
|
file should be added to
|
||||||
.Pa $HOME/.ssh/authorized_keys
|
.Pa $HOME/.ssh/authorized_keys
|
||||||
on all machines
|
on all machines
|
||||||
where you wish to log in using RSA authentication.
|
where you wish to log in using protocol version 1 RSA authentication.
|
||||||
The contents of the
|
The contents of the
|
||||||
.Pa $HOME/.ssh/id_dsa.pub
|
.Pa $HOME/.ssh/id_dsa.pub
|
||||||
|
and
|
||||||
|
.Pa $HOME/.ssh/id_rsa.pub
|
||||||
file should be added to
|
file should be added to
|
||||||
.Pa $HOME/.ssh/authorized_keys2
|
.Pa $HOME/.ssh/authorized_keys2
|
||||||
on all machines
|
on all machines
|
||||||
where you wish to log in using DSA authentication.
|
where you wish to log in using protocol version 2 DSA/RSA authentication.
|
||||||
These files are not
|
These files are not
|
||||||
sensitive and can (but need not) be readable by anyone.
|
sensitive and can (but need not) be readable by anyone.
|
||||||
These files are
|
These files are
|
||||||
@ -1098,15 +1241,15 @@ spaces).
|
|||||||
This file is not highly sensitive, but the recommended
|
This file is not highly sensitive, but the recommended
|
||||||
permissions are read/write for the user, and not accessible by others.
|
permissions are read/write for the user, and not accessible by others.
|
||||||
.It Pa $HOME/.ssh/authorized_keys2
|
.It Pa $HOME/.ssh/authorized_keys2
|
||||||
Lists the DSA keys that can be used for logging in as this user.
|
Lists the public keys (RSA/DSA) that can be used for logging in as this user.
|
||||||
This file is not highly sensitive, but the recommended
|
This file is not highly sensitive, but the recommended
|
||||||
permissions are read/write for the user, and not accessible by others.
|
permissions are read/write for the user, and not accessible by others.
|
||||||
.It Pa /etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2
|
.It Pa /etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2
|
||||||
Systemwide list of known host keys.
|
Systemwide list of known host keys.
|
||||||
.Pa /etc/ssh_known_hosts
|
.Pa /etc/ssh/ssh_known_hosts
|
||||||
contains RSA and
|
contains RSA and
|
||||||
.Pa /etc/ssh_known_hosts2
|
.Pa /etc/ssh/ssh_known_hosts2
|
||||||
contains DSA keys.
|
contains RSA or DSA keys for protocol version 2.
|
||||||
These files should be prepared by the
|
These files should be prepared by the
|
||||||
system administrator to contain the public host keys of all machines in the
|
system administrator to contain the public host keys of all machines in the
|
||||||
organization.
|
organization.
|
||||||
@ -1145,7 +1288,7 @@ also used by rlogin and rsh, which makes using this file insecure.)
|
|||||||
Each line of the file contains a host name (in the canonical form
|
Each line of the file contains a host name (in the canonical form
|
||||||
returned by name servers), and then a user name on that host,
|
returned by name servers), and then a user name on that host,
|
||||||
separated by a space.
|
separated by a space.
|
||||||
One some machines this file may need to be
|
On some machines this file may need to be
|
||||||
world-readable if the user's home directory is on a NFS partition,
|
world-readable if the user's home directory is on a NFS partition,
|
||||||
because
|
because
|
||||||
.Xr sshd 8
|
.Xr sshd 8
|
||||||
@ -1218,49 +1361,34 @@ manual page for more information.
|
|||||||
Contains additional definitions for environment variables, see section
|
Contains additional definitions for environment variables, see section
|
||||||
.Sx ENVIRONMENT
|
.Sx ENVIRONMENT
|
||||||
above.
|
above.
|
||||||
.It Pa libcrypto.so.X.1
|
|
||||||
A version of this library which includes support for the RSA algorithm
|
|
||||||
is required for proper operation.
|
|
||||||
.El
|
.El
|
||||||
.Sh AUTHOR
|
.Sh AUTHORS
|
||||||
OpenSSH
|
OpenSSH is a derivative of the original and free
|
||||||
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
|
ssh 1.2.12 release by Tatu Ylonen.
|
||||||
but with bugs removed and newer features re-added.
|
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
|
||||||
Rapidly after the
|
Theo de Raadt and Dug Song
|
||||||
1.2.12 release, newer versions of the original ssh bore successively
|
removed many bugs, re-added newer features and
|
||||||
more restrictive licenses, and thus demand for a free version was born.
|
created OpenSSH.
|
||||||
.Pp
|
Markus Friedl contributed the support for SSH
|
||||||
This version of OpenSSH
|
protocol versions 1.5 and 2.0.
|
||||||
.Bl -bullet
|
|
||||||
.It
|
|
||||||
has all components of a restrictive nature (i.e., patents, see
|
|
||||||
.Xr ssl 8 )
|
|
||||||
directly removed from the source code; any licensed or patented components
|
|
||||||
are chosen from
|
|
||||||
external libraries.
|
|
||||||
.It
|
|
||||||
has been updated to support SSH protocol 1.5 and 2, making it compatible with
|
|
||||||
all other SSH clients and servers.
|
|
||||||
.It
|
|
||||||
contains added support for
|
|
||||||
.Xr kerberos 8
|
|
||||||
authentication and ticket passing.
|
|
||||||
.It
|
|
||||||
supports one-time password authentication with
|
|
||||||
.Xr skey 1 .
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
OpenSSH has been created by Aaron Campbell, Bob Beck, Markus Friedl,
|
|
||||||
Niels Provos, Theo de Raadt, and Dug Song.
|
|
||||||
.Pp
|
|
||||||
The support for SSH protocol 2 was written by Markus Friedl.
|
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr rlogin 1 ,
|
.Xr rlogin 1 ,
|
||||||
.Xr rsh 1 ,
|
.Xr rsh 1 ,
|
||||||
.Xr scp 1 ,
|
.Xr scp 1 ,
|
||||||
|
.Xr sftp 1 ,
|
||||||
.Xr ssh-add 1 ,
|
.Xr ssh-add 1 ,
|
||||||
.Xr ssh-agent 1 ,
|
.Xr ssh-agent 1 ,
|
||||||
.Xr ssh-keygen 1 ,
|
.Xr ssh-keygen 1 ,
|
||||||
.Xr telnet 1 ,
|
.Xr telnet 1 ,
|
||||||
.Xr sshd 8 ,
|
.Xr sshd 8
|
||||||
.Xr ssl 8
|
.Rs
|
||||||
|
.%A T. Ylonen
|
||||||
|
.%A T. Kivinen
|
||||||
|
.%A M. Saarinen
|
||||||
|
.%A T. Rinne
|
||||||
|
.%A S. Lehtinen
|
||||||
|
.%T "SSH Protocol Architecture"
|
||||||
|
.%N draft-ietf-secsh-architecture-07.txt
|
||||||
|
.%D January 2001
|
||||||
|
.%O work in progress material
|
||||||
|
.Re
|
||||||
|
@ -39,26 +39,36 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: ssh.c,v 1.69 2000/10/27 07:32:19 markus Exp $");
|
RCSID("$OpenBSD: ssh.c,v 1.116 2001/04/17 12:55:04 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#include <openssl/dsa.h>
|
#include <openssl/err.h>
|
||||||
#include <openssl/rsa.h>
|
|
||||||
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "ssh.h"
|
#include "ssh.h"
|
||||||
#include "packet.h"
|
#include "ssh1.h"
|
||||||
#include "buffer.h"
|
|
||||||
#include "readconf.h"
|
|
||||||
#include "uidswap.h"
|
|
||||||
|
|
||||||
#include "ssh2.h"
|
#include "ssh2.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "cipher.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
#include "packet.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "uidswap.h"
|
||||||
#include "channels.h"
|
#include "channels.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
|
#include "pathnames.h"
|
||||||
|
#include "clientloop.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "readconf.h"
|
||||||
|
#include "sshconnect.h"
|
||||||
|
#include "tildexpand.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
#include "misc.h"
|
||||||
|
#include "kex.h"
|
||||||
|
#include "mac.h"
|
||||||
|
#include "sshtty.h"
|
||||||
|
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
@ -71,10 +81,11 @@ int debug_flag = 0;
|
|||||||
|
|
||||||
/* Flag indicating whether a tty should be allocated */
|
/* Flag indicating whether a tty should be allocated */
|
||||||
int tty_flag = 0;
|
int tty_flag = 0;
|
||||||
|
int no_tty_flag = 0;
|
||||||
|
int force_tty_flag = 0;
|
||||||
|
|
||||||
/* don't exec a shell */
|
/* don't exec a shell */
|
||||||
int no_shell_flag = 0;
|
int no_shell_flag = 0;
|
||||||
int no_tty_flag = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flag indicating that nothing should be read from stdin. This can be set
|
* Flag indicating that nothing should be read from stdin. This can be set
|
||||||
@ -113,14 +124,11 @@ struct sockaddr_storage hostaddr;
|
|||||||
*/
|
*/
|
||||||
volatile int received_window_change_signal = 0;
|
volatile int received_window_change_signal = 0;
|
||||||
|
|
||||||
/* Value of argv[0] (set in the main program). */
|
/* Private host keys. */
|
||||||
char *av0;
|
struct {
|
||||||
|
Key **keys;
|
||||||
/* Flag indicating whether we have a valid host private key loaded. */
|
int nkeys;
|
||||||
int host_private_key_loaded = 0;
|
} sensitive_data;
|
||||||
|
|
||||||
/* Host private key. */
|
|
||||||
RSA *host_private_key = NULL;
|
|
||||||
|
|
||||||
/* Original real UID. */
|
/* Original real UID. */
|
||||||
uid_t original_real_uid;
|
uid_t original_real_uid;
|
||||||
@ -128,23 +136,27 @@ uid_t original_real_uid;
|
|||||||
/* command to be executed */
|
/* command to be executed */
|
||||||
Buffer command;
|
Buffer command;
|
||||||
|
|
||||||
|
/* Should we execute a command or invoke a subsystem? */
|
||||||
|
int subsystem_flag = 0;
|
||||||
|
|
||||||
/* Prints a help message to the user. This function never returns. */
|
/* Prints a help message to the user. This function never returns. */
|
||||||
|
|
||||||
void
|
void
|
||||||
usage()
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s [options] host [command]\n", av0);
|
fprintf(stderr, "Usage: %s [options] host [command]\n", __progname);
|
||||||
fprintf(stderr, "Options:\n");
|
fprintf(stderr, "Options:\n");
|
||||||
fprintf(stderr, " -l user Log in using this user name.\n");
|
fprintf(stderr, " -l user Log in using this user name.\n");
|
||||||
fprintf(stderr, " -n Redirect input from /dev/null.\n");
|
fprintf(stderr, " -n Redirect input from " _PATH_DEVNULL ".\n");
|
||||||
fprintf(stderr, " -A Enable authentication agent forwarding.\n");
|
fprintf(stderr, " -A Enable authentication agent forwarding.\n");
|
||||||
fprintf(stderr, " -a Disable authentication agent forwarding.\n");
|
fprintf(stderr, " -a Disable authentication agent forwarding.\n");
|
||||||
#ifdef AFS
|
#ifdef AFS
|
||||||
fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n");
|
fprintf(stderr, " -k Disable Kerberos ticket and AFS token forwarding.\n");
|
||||||
#endif /* AFS */
|
#endif /* AFS */
|
||||||
fprintf(stderr, " -X Enable X11 connection forwarding.\n");
|
fprintf(stderr, " -X Enable X11 connection forwarding.\n");
|
||||||
fprintf(stderr, " -x Disable X11 connection forwarding.\n");
|
fprintf(stderr, " -x Disable X11 connection forwarding.\n");
|
||||||
fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\n");
|
fprintf(stderr, " -i file Identity for public key authentication "
|
||||||
|
"(default: ~/.ssh/identity)\n");
|
||||||
fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
|
fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
|
||||||
fprintf(stderr, " -T Do not allocate a tty.\n");
|
fprintf(stderr, " -T Do not allocate a tty.\n");
|
||||||
fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
|
fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
|
||||||
@ -156,20 +168,22 @@ usage()
|
|||||||
fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n");
|
fprintf(stderr, " -e char Set escape character; ``none'' = disable (default: ~).\n");
|
||||||
|
|
||||||
fprintf(stderr, " -c cipher Select encryption algorithm: "
|
fprintf(stderr, " -c cipher Select encryption algorithm: "
|
||||||
"``3des'', "
|
"``3des'', ``blowfish''\n");
|
||||||
"``blowfish''\n");
|
fprintf(stderr, " -m macs Specify MAC algorithms for protocol version 2.\n");
|
||||||
fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n");
|
fprintf(stderr, " -p port Connect to this port. Server must be on the same port.\n");
|
||||||
fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n");
|
fprintf(stderr, " -L listen-port:host:port Forward local port to remote address\n");
|
||||||
fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n");
|
fprintf(stderr, " -R listen-port:host:port Forward remote port to local address\n");
|
||||||
fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0);
|
fprintf(stderr, " These cause %s to listen for connections on a port, and\n", __progname);
|
||||||
fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
|
fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
|
||||||
fprintf(stderr, " -C Enable compression.\n");
|
fprintf(stderr, " -C Enable compression.\n");
|
||||||
fprintf(stderr, " -N Do not execute a shell or command.\n");
|
fprintf(stderr, " -N Do not execute a shell or command.\n");
|
||||||
fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n");
|
fprintf(stderr, " -g Allow remote hosts to connect to forwarded ports.\n");
|
||||||
|
fprintf(stderr, " -1 Force protocol version 1.\n");
|
||||||
|
fprintf(stderr, " -2 Force protocol version 2.\n");
|
||||||
fprintf(stderr, " -4 Use IPv4 only.\n");
|
fprintf(stderr, " -4 Use IPv4 only.\n");
|
||||||
fprintf(stderr, " -6 Use IPv6 only.\n");
|
fprintf(stderr, " -6 Use IPv6 only.\n");
|
||||||
fprintf(stderr, " -2 Force protocol version 2.\n");
|
|
||||||
fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n");
|
fprintf(stderr, " -o 'option' Process the option as if it was read from a configuration file.\n");
|
||||||
|
fprintf(stderr, " -s Invoke command (mandatory) as SSH2 subsystem.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,8 +228,9 @@ rsh_connect(char *host, char *user, Buffer * command)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssh_session(void);
|
int ssh_session(void);
|
||||||
int ssh_session2(void);
|
int ssh_session2(void);
|
||||||
|
void load_public_identity_files(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main program for the ssh client.
|
* Main program for the ssh client.
|
||||||
@ -227,7 +242,7 @@ main(int ac, char **av)
|
|||||||
u_short fwd_port, fwd_host_port;
|
u_short fwd_port, fwd_host_port;
|
||||||
char *optarg, *cp, buf[256];
|
char *optarg, *cp, buf[256];
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct passwd *pw, pwcopy;
|
struct passwd *pw;
|
||||||
int dummy;
|
int dummy;
|
||||||
uid_t original_effective_uid;
|
uid_t original_effective_uid;
|
||||||
|
|
||||||
@ -245,6 +260,15 @@ main(int ac, char **av)
|
|||||||
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
|
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
|
||||||
fatal("setrlimit failed: %.100s", strerror(errno));
|
fatal("setrlimit failed: %.100s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
/* Get user data. */
|
||||||
|
pw = getpwuid(original_real_uid);
|
||||||
|
if (!pw) {
|
||||||
|
log("You don't exist, go away!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
/* Take a copy of the returned structure. */
|
||||||
|
pw = pwcopy(pw);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use uid-swapping to give up root privileges for the duration of
|
* Use uid-swapping to give up root privileges for the duration of
|
||||||
* option processing. We will re-instantiate the rights when we are
|
* option processing. We will re-instantiate the rights when we are
|
||||||
@ -252,7 +276,7 @@ main(int ac, char **av)
|
|||||||
* them when the port has been created (actually, when the connection
|
* them when the port has been created (actually, when the connection
|
||||||
* has been made, as we may need to create the port several times).
|
* has been made, as we may need to create the port several times).
|
||||||
*/
|
*/
|
||||||
temporarily_use_uid(original_real_uid);
|
temporarily_use_uid(pw);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set our umask to something reasonable, as some files are created
|
* Set our umask to something reasonable, as some files are created
|
||||||
@ -262,24 +286,12 @@ main(int ac, char **av)
|
|||||||
*/
|
*/
|
||||||
umask(022);
|
umask(022);
|
||||||
|
|
||||||
/* Save our own name. */
|
|
||||||
av0 = av[0];
|
|
||||||
|
|
||||||
/* Initialize option structure to indicate that no values have been set. */
|
/* Initialize option structure to indicate that no values have been set. */
|
||||||
initialize_options(&options);
|
initialize_options(&options);
|
||||||
|
|
||||||
/* Parse command-line arguments. */
|
/* Parse command-line arguments. */
|
||||||
host = NULL;
|
host = NULL;
|
||||||
|
|
||||||
/* If program name is not one of the standard names, use it as host name. */
|
|
||||||
if (strchr(av0, '/'))
|
|
||||||
cp = strrchr(av0, '/') + 1;
|
|
||||||
else
|
|
||||||
cp = av0;
|
|
||||||
if (strcmp(cp, "rsh") && strcmp(cp, "ssh") && strcmp(cp, "rlogin") &&
|
|
||||||
strcmp(cp, "slogin") && strcmp(cp, "remsh"))
|
|
||||||
host = cp;
|
|
||||||
|
|
||||||
for (optind = 1; optind < ac; optind++) {
|
for (optind = 1; optind < ac; optind++) {
|
||||||
if (av[optind][0] != '-') {
|
if (av[optind][0] != '-') {
|
||||||
if (host)
|
if (host)
|
||||||
@ -297,7 +309,7 @@ main(int ac, char **av)
|
|||||||
opt = av[optind][1];
|
opt = av[optind][1];
|
||||||
if (!opt)
|
if (!opt)
|
||||||
usage();
|
usage();
|
||||||
if (strchr("eilcpLRo", opt)) { /* options with arguments */
|
if (strchr("eilcmpLRDo", opt)) { /* options with arguments */
|
||||||
optarg = av[optind] + 2;
|
optarg = av[optind] + 2;
|
||||||
if (strcmp(optarg, "") == 0) {
|
if (strcmp(optarg, "") == 0) {
|
||||||
if (optind >= ac - 1)
|
if (optind >= ac - 1)
|
||||||
@ -310,6 +322,9 @@ main(int ac, char **av)
|
|||||||
optarg = NULL;
|
optarg = NULL;
|
||||||
}
|
}
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
case '1':
|
||||||
|
options.protocol = SSH_PROTO_1;
|
||||||
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
options.protocol = SSH_PROTO_2;
|
options.protocol = SSH_PROTO_2;
|
||||||
break;
|
break;
|
||||||
@ -354,16 +369,17 @@ main(int ac, char **av)
|
|||||||
case 'i':
|
case 'i':
|
||||||
if (stat(optarg, &st) < 0) {
|
if (stat(optarg, &st) < 0) {
|
||||||
fprintf(stderr, "Warning: Identity file %s does not exist.\n",
|
fprintf(stderr, "Warning: Identity file %s does not exist.\n",
|
||||||
optarg);
|
optarg);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
|
if (options.num_identity_files >= SSH_MAX_IDENTITY_FILES)
|
||||||
fatal("Too many identity files specified (max %d)",
|
fatal("Too many identity files specified (max %d)",
|
||||||
SSH_MAX_IDENTITY_FILES);
|
SSH_MAX_IDENTITY_FILES);
|
||||||
options.identity_files[options.num_identity_files++] =
|
options.identity_files[options.num_identity_files++] = xstrdup(optarg);
|
||||||
xstrdup(optarg);
|
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
|
if (tty_flag)
|
||||||
|
force_tty_flag = 1;
|
||||||
tty_flag = 1;
|
tty_flag = 1;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
@ -374,15 +390,16 @@ main(int ac, char **av)
|
|||||||
options.log_level++;
|
options.log_level++;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
fatal("Too high debugging level.\n");
|
fatal("Too high debugging level.");
|
||||||
}
|
}
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case 'V':
|
case 'V':
|
||||||
fprintf(stderr, "SSH Version %s, protocol versions %d.%d/%d.%d.\n",
|
fprintf(stderr,
|
||||||
|
"%s, SSH protocols %d.%d/%d.%d, OpenSSL 0x%8.8lx\n",
|
||||||
SSH_VERSION,
|
SSH_VERSION,
|
||||||
PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
|
PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
|
||||||
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2);
|
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
|
||||||
fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay());
|
SSLeay());
|
||||||
if (opt == 'V')
|
if (opt == 'V')
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
@ -391,10 +408,10 @@ main(int ac, char **av)
|
|||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
if (optarg[0] == '^' && optarg[2] == 0 &&
|
if (optarg[0] == '^' && optarg[2] == 0 &&
|
||||||
(unsigned char) optarg[1] >= 64 && (unsigned char) optarg[1] < 128)
|
(u_char) optarg[1] >= 64 && (u_char) optarg[1] < 128)
|
||||||
options.escape_char = (unsigned char) optarg[1] & 31;
|
options.escape_char = (u_char) optarg[1] & 31;
|
||||||
else if (strlen(optarg) == 1)
|
else if (strlen(optarg) == 1)
|
||||||
options.escape_char = (unsigned char) optarg[0];
|
options.escape_char = (u_char) optarg[0];
|
||||||
else if (strcmp(optarg, "none") == 0)
|
else if (strcmp(optarg, "none") == 0)
|
||||||
options.escape_char = -2;
|
options.escape_char = -2;
|
||||||
else {
|
else {
|
||||||
@ -409,16 +426,34 @@ main(int ac, char **av)
|
|||||||
options.cipher = SSH_CIPHER_ILLEGAL;
|
options.cipher = SSH_CIPHER_ILLEGAL;
|
||||||
} else {
|
} else {
|
||||||
/* SSH1 only */
|
/* SSH1 only */
|
||||||
Cipher *c = cipher_by_name(optarg);
|
options.cipher = cipher_number(optarg);
|
||||||
if (c == NULL || c->number < 0) {
|
if (options.cipher == -1) {
|
||||||
fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
|
fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
options.cipher = c->number;
|
if (options.cipher == SSH_CIPHER_3DES) {
|
||||||
|
options.ciphers = "3des-cbc";
|
||||||
|
} else if (options.cipher == SSH_CIPHER_BLOWFISH) {
|
||||||
|
options.ciphers = "blowfish-cbc";
|
||||||
|
} else {
|
||||||
|
options.ciphers = (char *)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
if (mac_valid(optarg))
|
||||||
|
options.macs = xstrdup(optarg);
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "Unknown mac type '%s'\n", optarg);
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
options.port = atoi(optarg);
|
options.port = a2port(optarg);
|
||||||
|
if (options.port == 0) {
|
||||||
|
fprintf(stderr, "Bad port '%s'\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
options.user = optarg;
|
options.user = optarg;
|
||||||
@ -445,6 +480,16 @@ main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
add_local_forward(&options, fwd_port, buf, fwd_host_port);
|
add_local_forward(&options, fwd_port, buf, fwd_host_port);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'D':
|
||||||
|
fwd_port = a2port(optarg);
|
||||||
|
if (fwd_port == 0) {
|
||||||
|
fprintf(stderr, "Bad dynamic port '%s'\n", optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
add_local_forward(&options, fwd_port, "socks4", 0);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
options.compression = 1;
|
options.compression = 1;
|
||||||
break;
|
break;
|
||||||
@ -461,6 +506,9 @@ main(int ac, char **av)
|
|||||||
"command-line", 0, &dummy) != 0)
|
"command-line", 0, &dummy) != 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
subsystem_flag = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
@ -471,6 +519,7 @@ main(int ac, char **av)
|
|||||||
usage();
|
usage();
|
||||||
|
|
||||||
SSLeay_add_all_algorithms();
|
SSLeay_add_all_algorithms();
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
|
||||||
/* Initialize the command to execute on remote host. */
|
/* Initialize the command to execute on remote host. */
|
||||||
buffer_init(&command);
|
buffer_init(&command);
|
||||||
@ -483,6 +532,10 @@ main(int ac, char **av)
|
|||||||
if (optind == ac) {
|
if (optind == ac) {
|
||||||
/* No command specified - execute shell on a tty. */
|
/* No command specified - execute shell on a tty. */
|
||||||
tty_flag = 1;
|
tty_flag = 1;
|
||||||
|
if (subsystem_flag) {
|
||||||
|
fprintf(stderr, "You must specify a subsystem to invoke.\n");
|
||||||
|
usage();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* A command has been specified. Store it into the
|
/* A command has been specified. Store it into the
|
||||||
buffer. */
|
buffer. */
|
||||||
@ -501,65 +554,35 @@ main(int ac, char **av)
|
|||||||
if (buffer_len(&command) == 0)
|
if (buffer_len(&command) == 0)
|
||||||
tty_flag = 1;
|
tty_flag = 1;
|
||||||
|
|
||||||
/* Do not allocate a tty if stdin is not a tty. */
|
/* Force no tty*/
|
||||||
if (!isatty(fileno(stdin))) {
|
|
||||||
if (tty_flag)
|
|
||||||
fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
|
|
||||||
tty_flag = 0;
|
|
||||||
}
|
|
||||||
/* force */
|
|
||||||
if (no_tty_flag)
|
if (no_tty_flag)
|
||||||
tty_flag = 0;
|
tty_flag = 0;
|
||||||
|
/* Do not allocate a tty if stdin is not a tty. */
|
||||||
/* Get user data. */
|
if (!isatty(fileno(stdin)) && !force_tty_flag) {
|
||||||
pw = getpwuid(original_real_uid);
|
if (tty_flag)
|
||||||
if (!pw) {
|
log("Pseudo-terminal will not be allocated because stdin is not a terminal.");
|
||||||
fprintf(stderr, "You don't exist, go away!\n");
|
tty_flag = 0;
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
/* Take a copy of the returned structure. */
|
|
||||||
memset(&pwcopy, 0, sizeof(pwcopy));
|
|
||||||
pwcopy.pw_name = xstrdup(pw->pw_name);
|
|
||||||
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
|
|
||||||
pwcopy.pw_uid = pw->pw_uid;
|
|
||||||
pwcopy.pw_gid = pw->pw_gid;
|
|
||||||
pwcopy.pw_dir = xstrdup(pw->pw_dir);
|
|
||||||
pwcopy.pw_shell = xstrdup(pw->pw_shell);
|
|
||||||
pwcopy.pw_class = xstrdup(pw->pw_class);
|
|
||||||
pwcopy.pw_expire = pw->pw_expire;
|
|
||||||
pwcopy.pw_change = pw->pw_change;
|
|
||||||
pw = &pwcopy;
|
|
||||||
|
|
||||||
/* Initialize "log" output. Since we are the client all output
|
/*
|
||||||
actually goes to the terminal. */
|
* Initialize "log" output. Since we are the client all output
|
||||||
log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
|
* actually goes to stderr.
|
||||||
|
*/
|
||||||
|
log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level,
|
||||||
|
SYSLOG_FACILITY_USER, 1);
|
||||||
|
|
||||||
/* Read per-user configuration file. */
|
/* Read per-user configuration file. */
|
||||||
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_CONFFILE);
|
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_CONFFILE);
|
||||||
read_config_file(buf, host, &options);
|
read_config_file(buf, host, &options);
|
||||||
|
|
||||||
/* Read systemwide configuration file. */
|
/* Read systemwide configuration file. */
|
||||||
read_config_file(HOST_CONFIG_FILE, host, &options);
|
read_config_file(_PATH_HOST_CONFIG_FILE, host, &options);
|
||||||
|
|
||||||
/* Fill configuration defaults. */
|
/* Fill configuration defaults. */
|
||||||
fill_default_options(&options);
|
fill_default_options(&options);
|
||||||
|
|
||||||
/* reinit */
|
/* reinit */
|
||||||
log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
|
log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1);
|
||||||
|
|
||||||
/* check if RSA support exists */
|
|
||||||
if ((options.protocol & SSH_PROTO_1) &&
|
|
||||||
rsa_alive() == 0) {
|
|
||||||
log("%s: no RSA support in libssl and libcrypto. See ssl(8).",
|
|
||||||
__progname);
|
|
||||||
log("Disabling protocol version 1");
|
|
||||||
options.protocol &= ~ (SSH_PROTO_1|SSH_PROTO_1_PREFERRED);
|
|
||||||
}
|
|
||||||
if (! options.protocol & (SSH_PROTO_1|SSH_PROTO_2)) {
|
|
||||||
fprintf(stderr, "%s: No protocol version available.\n",
|
|
||||||
__progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.user == NULL)
|
if (options.user == NULL)
|
||||||
options.user = xstrdup(pw->pw_name);
|
options.user = xstrdup(pw->pw_name);
|
||||||
@ -585,8 +608,9 @@ main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
/* Disable rhosts authentication if not running as root. */
|
/* Disable rhosts authentication if not running as root. */
|
||||||
if (original_effective_uid != 0 || !options.use_privileged_port) {
|
if (original_effective_uid != 0 || !options.use_privileged_port) {
|
||||||
|
debug("Rhosts Authentication disabled, "
|
||||||
|
"originating port will not be trusted.");
|
||||||
options.rhosts_authentication = 0;
|
options.rhosts_authentication = 0;
|
||||||
options.rhosts_rsa_authentication = 0;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If using rsh has been selected, exec it now (without trying
|
* If using rsh has been selected, exec it now (without trying
|
||||||
@ -600,7 +624,7 @@ main(int ac, char **av)
|
|||||||
restore_uid();
|
restore_uid();
|
||||||
|
|
||||||
/* Switch to the original uid permanently. */
|
/* Switch to the original uid permanently. */
|
||||||
permanently_set_uid(original_real_uid);
|
permanently_set_uid(pw);
|
||||||
|
|
||||||
/* Execute rsh. */
|
/* Execute rsh. */
|
||||||
rsh_connect(host, options.user, &command);
|
rsh_connect(host, options.user, &command);
|
||||||
@ -609,17 +633,12 @@ main(int ac, char **av)
|
|||||||
/* Restore our superuser privileges. */
|
/* Restore our superuser privileges. */
|
||||||
restore_uid();
|
restore_uid();
|
||||||
|
|
||||||
/*
|
/* Open a connection to the remote host. */
|
||||||
* Open a connection to the remote host. This needs root privileges
|
|
||||||
* if rhosts_{rsa_}authentication is enabled.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ok = ssh_connect(host, &hostaddr, options.port,
|
ok = ssh_connect(host, &hostaddr, options.port,
|
||||||
options.connection_attempts,
|
options.connection_attempts,
|
||||||
!options.rhosts_authentication &&
|
original_effective_uid != 0 || !options.use_privileged_port,
|
||||||
!options.rhosts_rsa_authentication,
|
pw, options.proxy_command);
|
||||||
original_real_uid,
|
|
||||||
options.proxy_command);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we successfully made the connection, load the host private key
|
* If we successfully made the connection, load the host private key
|
||||||
@ -627,13 +646,18 @@ main(int ac, char **av)
|
|||||||
* authentication. This must be done before releasing extra
|
* authentication. This must be done before releasing extra
|
||||||
* privileges, because the file is only readable by root.
|
* privileges, because the file is only readable by root.
|
||||||
*/
|
*/
|
||||||
if (ok && (options.protocol & SSH_PROTO_1)) {
|
sensitive_data.nkeys = 0;
|
||||||
Key k;
|
sensitive_data.keys = NULL;
|
||||||
host_private_key = RSA_new();
|
if (ok && (options.rhosts_rsa_authentication ||
|
||||||
k.type = KEY_RSA;
|
options.hostbased_authentication)) {
|
||||||
k.rsa = host_private_key;
|
sensitive_data.nkeys = 3;
|
||||||
if (load_private_key(HOST_KEY_FILE, "", &k, NULL))
|
sensitive_data.keys = xmalloc(sensitive_data.nkeys*sizeof(Key));
|
||||||
host_private_key_loaded = 1;
|
sensitive_data.keys[0] = key_load_private_type(KEY_RSA1,
|
||||||
|
_PATH_HOST_KEY_FILE, "", NULL);
|
||||||
|
sensitive_data.keys[1] = key_load_private_type(KEY_DSA,
|
||||||
|
_PATH_HOST_DSA_KEY_FILE, "", NULL);
|
||||||
|
sensitive_data.keys[2] = key_load_private_type(KEY_RSA,
|
||||||
|
_PATH_HOST_RSA_KEY_FILE, "", NULL);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Get rid of any extra privileges that we may have. We will no
|
* Get rid of any extra privileges that we may have. We will no
|
||||||
@ -650,13 +674,13 @@ main(int ac, char **av)
|
|||||||
* process, read the private hostkey and impersonate the host.
|
* process, read the private hostkey and impersonate the host.
|
||||||
* OpenBSD does not allow ptracing of setuid processes.
|
* OpenBSD does not allow ptracing of setuid processes.
|
||||||
*/
|
*/
|
||||||
permanently_set_uid(original_real_uid);
|
permanently_set_uid(pw);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that we are back to our own permissions, create ~/.ssh
|
* Now that we are back to our own permissions, create ~/.ssh
|
||||||
* directory if it doesn\'t already exist.
|
* directory if it doesn\'t already exist.
|
||||||
*/
|
*/
|
||||||
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
|
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_DIR);
|
||||||
if (stat(buf, &st) < 0)
|
if (stat(buf, &st) < 0)
|
||||||
if (mkdir(buf, 0700) < 0)
|
if (mkdir(buf, 0700) < 0)
|
||||||
error("Could not create directory '%.200s'.", buf);
|
error("Could not create directory '%.200s'.", buf);
|
||||||
@ -677,31 +701,36 @@ main(int ac, char **av)
|
|||||||
}
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/* Expand ~ in options.identity_files. */
|
/* load options.identity_files */
|
||||||
/* XXX mem-leaks */
|
load_public_identity_files();
|
||||||
for (i = 0; i < options.num_identity_files; i++)
|
|
||||||
options.identity_files[i] =
|
|
||||||
tilde_expand_filename(options.identity_files[i], original_real_uid);
|
|
||||||
for (i = 0; i < options.num_identity_files2; i++)
|
|
||||||
options.identity_files2[i] =
|
|
||||||
tilde_expand_filename(options.identity_files2[i], original_real_uid);
|
|
||||||
/* Expand ~ in known host file names. */
|
/* Expand ~ in known host file names. */
|
||||||
options.system_hostfile = tilde_expand_filename(options.system_hostfile,
|
/* XXX mem-leaks: */
|
||||||
original_real_uid);
|
options.system_hostfile =
|
||||||
options.user_hostfile = tilde_expand_filename(options.user_hostfile,
|
tilde_expand_filename(options.system_hostfile, original_real_uid);
|
||||||
original_real_uid);
|
options.user_hostfile =
|
||||||
options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2,
|
tilde_expand_filename(options.user_hostfile, original_real_uid);
|
||||||
original_real_uid);
|
options.system_hostfile2 =
|
||||||
options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2,
|
tilde_expand_filename(options.system_hostfile2, original_real_uid);
|
||||||
original_real_uid);
|
options.user_hostfile2 =
|
||||||
|
tilde_expand_filename(options.user_hostfile2, original_real_uid);
|
||||||
|
|
||||||
/* Log into the remote system. This never returns if the login fails. */
|
/* Log into the remote system. This never returns if the login fails. */
|
||||||
ssh_login(host_private_key_loaded, host_private_key,
|
ssh_login(sensitive_data.keys, sensitive_data.nkeys,
|
||||||
host, (struct sockaddr *)&hostaddr, original_real_uid);
|
host, (struct sockaddr *)&hostaddr, pw);
|
||||||
|
|
||||||
/* We no longer need the host private key. Clear it now. */
|
/* We no longer need the private host keys. Clear them now. */
|
||||||
if (host_private_key_loaded)
|
if (sensitive_data.nkeys != 0) {
|
||||||
RSA_free(host_private_key); /* Destroys contents safely */
|
for (i = 0; i < sensitive_data.nkeys; i++) {
|
||||||
|
if (sensitive_data.keys[i] != NULL) {
|
||||||
|
/* Destroys contents safely */
|
||||||
|
debug3("clear hostkey %d", i);
|
||||||
|
key_free(sensitive_data.keys[i]);
|
||||||
|
sensitive_data.keys[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xfree(sensitive_data.keys);
|
||||||
|
}
|
||||||
|
|
||||||
exit_status = compat20 ? ssh_session2() : ssh_session();
|
exit_status = compat20 ? ssh_session2() : ssh_session();
|
||||||
packet_close();
|
packet_close();
|
||||||
@ -717,7 +746,7 @@ x11_get_proto(char *proto, int proto_len, char *data, int data_len)
|
|||||||
|
|
||||||
if (options.xauth_location) {
|
if (options.xauth_location) {
|
||||||
/* Try to get Xauthority information for the display. */
|
/* Try to get Xauthority information for the display. */
|
||||||
snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
|
snprintf(line, sizeof line, "%.100s list %.200s 2>" _PATH_DEVNULL,
|
||||||
options.xauth_location, getenv("DISPLAY"));
|
options.xauth_location, getenv("DISPLAY"));
|
||||||
f = popen(line, "r");
|
f = popen(line, "r");
|
||||||
if (f && fgets(line, sizeof(line), f) &&
|
if (f && fgets(line, sizeof(line), f) &&
|
||||||
@ -747,16 +776,61 @@ x11_get_proto(char *proto, int proto_len, char *data, int data_len)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ssh_init_forwarding(void)
|
||||||
|
{
|
||||||
|
int success = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Initiate local TCP/IP port forwardings. */
|
||||||
|
for (i = 0; i < options.num_local_forwards; i++) {
|
||||||
|
debug("Connections to local port %d forwarded to remote address %.200s:%d",
|
||||||
|
options.local_forwards[i].port,
|
||||||
|
options.local_forwards[i].host,
|
||||||
|
options.local_forwards[i].host_port);
|
||||||
|
success += channel_request_local_forwarding(
|
||||||
|
options.local_forwards[i].port,
|
||||||
|
options.local_forwards[i].host,
|
||||||
|
options.local_forwards[i].host_port,
|
||||||
|
options.gateway_ports);
|
||||||
|
}
|
||||||
|
if (i > 0 && success == 0)
|
||||||
|
error("Could not request local forwarding.");
|
||||||
|
|
||||||
|
/* Initiate remote TCP/IP port forwardings. */
|
||||||
|
for (i = 0; i < options.num_remote_forwards; i++) {
|
||||||
|
debug("Connections to remote port %d forwarded to local address %.200s:%d",
|
||||||
|
options.remote_forwards[i].port,
|
||||||
|
options.remote_forwards[i].host,
|
||||||
|
options.remote_forwards[i].host_port);
|
||||||
|
channel_request_remote_forwarding(
|
||||||
|
options.remote_forwards[i].port,
|
||||||
|
options.remote_forwards[i].host,
|
||||||
|
options.remote_forwards[i].host_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
check_agent_present(void)
|
||||||
|
{
|
||||||
|
if (options.forward_agent) {
|
||||||
|
/* Clear agent forwarding if we don\'t have an agent. */
|
||||||
|
int authfd = ssh_get_authentication_socket();
|
||||||
|
if (authfd < 0)
|
||||||
|
options.forward_agent = 0;
|
||||||
|
else
|
||||||
|
ssh_close_authentication_socket(authfd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_session(void)
|
ssh_session(void)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
int i;
|
|
||||||
int plen;
|
int plen;
|
||||||
int interactive = 0;
|
int interactive = 0;
|
||||||
int have_tty = 0;
|
int have_tty = 0;
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
int authfd;
|
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
/* Enable compression if requested. */
|
/* Enable compression if requested. */
|
||||||
@ -802,7 +876,7 @@ ssh_session(void)
|
|||||||
packet_put_int(ws.ws_ypixel);
|
packet_put_int(ws.ws_ypixel);
|
||||||
|
|
||||||
/* Store tty modes in the packet. */
|
/* Store tty modes in the packet. */
|
||||||
tty_make_modes(fileno(stdin));
|
tty_make_modes(fileno(stdin), NULL);
|
||||||
|
|
||||||
/* Send the packet, and wait for it to leave. */
|
/* Send the packet, and wait for it to leave. */
|
||||||
packet_send();
|
packet_send();
|
||||||
@ -838,16 +912,11 @@ ssh_session(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Tell the packet module whether this is an interactive session. */
|
/* Tell the packet module whether this is an interactive session. */
|
||||||
packet_set_interactive(interactive, options.keepalives);
|
packet_set_interactive(interactive);
|
||||||
|
|
||||||
/* Clear agent forwarding if we don\'t have an agent. */
|
|
||||||
authfd = ssh_get_authentication_socket();
|
|
||||||
if (authfd < 0)
|
|
||||||
options.forward_agent = 0;
|
|
||||||
else
|
|
||||||
ssh_close_authentication_socket(authfd);
|
|
||||||
|
|
||||||
/* Request authentication agent forwarding if appropriate. */
|
/* Request authentication agent forwarding if appropriate. */
|
||||||
|
check_agent_present();
|
||||||
|
|
||||||
if (options.forward_agent) {
|
if (options.forward_agent) {
|
||||||
debug("Requesting authentication agent forwarding.");
|
debug("Requesting authentication agent forwarding.");
|
||||||
auth_request_forwarding();
|
auth_request_forwarding();
|
||||||
@ -858,28 +927,9 @@ ssh_session(void)
|
|||||||
if (type != SSH_SMSG_SUCCESS)
|
if (type != SSH_SMSG_SUCCESS)
|
||||||
log("Warning: Remote host denied authentication agent forwarding.");
|
log("Warning: Remote host denied authentication agent forwarding.");
|
||||||
}
|
}
|
||||||
/* Initiate local TCP/IP port forwardings. */
|
|
||||||
for (i = 0; i < options.num_local_forwards; i++) {
|
|
||||||
debug("Connections to local port %d forwarded to remote address %.200s:%d",
|
|
||||||
options.local_forwards[i].port,
|
|
||||||
options.local_forwards[i].host,
|
|
||||||
options.local_forwards[i].host_port);
|
|
||||||
channel_request_local_forwarding(options.local_forwards[i].port,
|
|
||||||
options.local_forwards[i].host,
|
|
||||||
options.local_forwards[i].host_port,
|
|
||||||
options.gateway_ports);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initiate remote TCP/IP port forwardings. */
|
/* Initiate port forwardings. */
|
||||||
for (i = 0; i < options.num_remote_forwards; i++) {
|
ssh_init_forwarding();
|
||||||
debug("Connections to remote port %d forwarded to local address %.200s:%d",
|
|
||||||
options.remote_forwards[i].port,
|
|
||||||
options.remote_forwards[i].host,
|
|
||||||
options.remote_forwards[i].host_port);
|
|
||||||
channel_request_remote_forwarding(options.remote_forwards[i].port,
|
|
||||||
options.remote_forwards[i].host,
|
|
||||||
options.remote_forwards[i].host_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If requested, let ssh continue in the background. */
|
/* If requested, let ssh continue in the background. */
|
||||||
if (fork_after_authentication_flag)
|
if (fork_after_authentication_flag)
|
||||||
@ -911,32 +961,28 @@ ssh_session(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
init_local_fwd(void)
|
client_subsystem_reply(int type, int plen, void *ctxt)
|
||||||
{
|
{
|
||||||
int i;
|
int id, len;
|
||||||
/* Initiate local TCP/IP port forwardings. */
|
|
||||||
for (i = 0; i < options.num_local_forwards; i++) {
|
id = packet_get_int();
|
||||||
debug("Connections to local port %d forwarded to remote address %.200s:%d",
|
len = buffer_len(&command);
|
||||||
options.local_forwards[i].port,
|
if (len > 900)
|
||||||
options.local_forwards[i].host,
|
len = 900;
|
||||||
options.local_forwards[i].host_port);
|
packet_done();
|
||||||
channel_request_local_forwarding(options.local_forwards[i].port,
|
if (type == SSH2_MSG_CHANNEL_FAILURE)
|
||||||
options.local_forwards[i].host,
|
fatal("Request for subsystem '%.*s' failed on channel %d",
|
||||||
options.local_forwards[i].host_port,
|
len, buffer_ptr(&command), id);
|
||||||
options.gateway_ports);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void client_set_session_ident(int id);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
client_init(int id, void *arg)
|
ssh_session2_callback(int id, void *arg)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
debug("client_init id %d arg %d", id, (int)arg);
|
int interactive = 0;
|
||||||
|
struct termios tio;
|
||||||
|
|
||||||
if (no_shell_flag)
|
debug("client_init id %d arg %ld", id, (long)arg);
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (tty_flag) {
|
if (tty_flag) {
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
@ -954,8 +1000,10 @@ client_init(int id, void *arg)
|
|||||||
packet_put_int(ws.ws_row);
|
packet_put_int(ws.ws_row);
|
||||||
packet_put_int(ws.ws_xpixel);
|
packet_put_int(ws.ws_xpixel);
|
||||||
packet_put_int(ws.ws_ypixel);
|
packet_put_int(ws.ws_ypixel);
|
||||||
packet_put_cstring(""); /* XXX: encode terminal modes */
|
tio = get_saved_tio();
|
||||||
|
tty_make_modes(/*ignored*/ 0, &tio);
|
||||||
packet_send();
|
packet_send();
|
||||||
|
interactive = 1;
|
||||||
/* XXX wait for reply */
|
/* XXX wait for reply */
|
||||||
}
|
}
|
||||||
if (options.forward_x11 &&
|
if (options.forward_x11 &&
|
||||||
@ -966,34 +1014,51 @@ client_init(int id, void *arg)
|
|||||||
/* Request forwarding with authentication spoofing. */
|
/* Request forwarding with authentication spoofing. */
|
||||||
debug("Requesting X11 forwarding with authentication spoofing.");
|
debug("Requesting X11 forwarding with authentication spoofing.");
|
||||||
x11_request_forwarding_with_spoofing(id, proto, data);
|
x11_request_forwarding_with_spoofing(id, proto, data);
|
||||||
|
interactive = 1;
|
||||||
/* XXX wait for reply */
|
/* XXX wait for reply */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_agent_present();
|
||||||
|
if (options.forward_agent) {
|
||||||
|
debug("Requesting authentication agent forwarding.");
|
||||||
|
channel_request_start(id, "auth-agent-req@openssh.com", 0);
|
||||||
|
packet_send();
|
||||||
|
}
|
||||||
|
|
||||||
len = buffer_len(&command);
|
len = buffer_len(&command);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
if (len > 900)
|
if (len > 900)
|
||||||
len = 900;
|
len = 900;
|
||||||
debug("Sending command: %.*s", len, buffer_ptr(&command));
|
if (subsystem_flag) {
|
||||||
channel_request_start(id, "exec", 0);
|
debug("Sending subsystem: %.*s", len, buffer_ptr(&command));
|
||||||
packet_put_string(buffer_ptr(&command), len);
|
channel_request_start(id, "subsystem", /*want reply*/ 1);
|
||||||
|
/* register callback for reply */
|
||||||
|
/* XXX we asume 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 {
|
||||||
|
debug("Sending command: %.*s", len, buffer_ptr(&command));
|
||||||
|
channel_request_start(id, "exec", 0);
|
||||||
|
}
|
||||||
|
packet_put_string(buffer_ptr(&command), buffer_len(&command));
|
||||||
packet_send();
|
packet_send();
|
||||||
} else {
|
} else {
|
||||||
channel_request(id, "shell", 0);
|
channel_request(id, "shell", 0);
|
||||||
}
|
}
|
||||||
/* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */
|
/* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */
|
||||||
done:
|
|
||||||
/* register different callback, etc. XXX */
|
/* register different callback, etc. XXX */
|
||||||
client_set_session_ident(id);
|
packet_set_interactive(interactive);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ssh_session2(void)
|
ssh_session2_command(void)
|
||||||
{
|
{
|
||||||
int window, packetmax, id;
|
int id, window, packetmax;
|
||||||
int in, out, err;
|
int in, out, err;
|
||||||
|
|
||||||
if (stdin_null_flag) {
|
if (stdin_null_flag) {
|
||||||
in = open("/dev/null", O_RDONLY);
|
in = open(_PATH_DEVNULL, O_RDONLY);
|
||||||
} else {
|
} else {
|
||||||
in = dup(STDIN_FILENO);
|
in = dup(STDIN_FILENO);
|
||||||
}
|
}
|
||||||
@ -1011,14 +1076,6 @@ ssh_session2(void)
|
|||||||
if (!isatty(err))
|
if (!isatty(err))
|
||||||
set_nonblock(err);
|
set_nonblock(err);
|
||||||
|
|
||||||
/* should be pre-session */
|
|
||||||
init_local_fwd();
|
|
||||||
|
|
||||||
/* If requested, let ssh continue in the background. */
|
|
||||||
if (fork_after_authentication_flag)
|
|
||||||
if (daemon(1, 1) < 0)
|
|
||||||
fatal("daemon() failed: %.200s", strerror(errno));
|
|
||||||
|
|
||||||
window = CHAN_SES_WINDOW_DEFAULT;
|
window = CHAN_SES_WINDOW_DEFAULT;
|
||||||
packetmax = CHAN_SES_PACKET_DEFAULT;
|
packetmax = CHAN_SES_PACKET_DEFAULT;
|
||||||
if (!tty_flag) {
|
if (!tty_flag) {
|
||||||
@ -1030,8 +1087,48 @@ ssh_session2(void)
|
|||||||
window, packetmax, CHAN_EXTENDED_WRITE,
|
window, packetmax, CHAN_EXTENDED_WRITE,
|
||||||
xstrdup("client-session"), /*nonblock*/0);
|
xstrdup("client-session"), /*nonblock*/0);
|
||||||
|
|
||||||
|
debug("channel_new: %d", id);
|
||||||
|
|
||||||
channel_open(id);
|
channel_open(id);
|
||||||
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
|
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION,
|
||||||
|
ssh_session2_callback, (void *)0);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ssh_session2(void)
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
|
||||||
|
/* XXX should be pre-session */
|
||||||
|
ssh_init_forwarding();
|
||||||
|
|
||||||
|
id = no_shell_flag ? -1 : ssh_session2_command();
|
||||||
|
|
||||||
|
/* If requested, let ssh continue in the background. */
|
||||||
|
if (fork_after_authentication_flag)
|
||||||
|
if (daemon(1, 1) < 0)
|
||||||
|
fatal("daemon() failed: %.200s", strerror(errno));
|
||||||
|
|
||||||
return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
|
return client_loop(tty_flag, tty_flag ? options.escape_char : -1, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
load_public_identity_files(void)
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
Key *public;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < options.num_identity_files; i++) {
|
||||||
|
filename = tilde_expand_filename(options.identity_files[i],
|
||||||
|
original_real_uid);
|
||||||
|
public = key_load_public(filename, NULL);
|
||||||
|
debug("identity file %s type %d", filename,
|
||||||
|
public ? public->type : -1);
|
||||||
|
xfree(options.identity_files[i]);
|
||||||
|
options.identity_files[i] = filename;
|
||||||
|
options.identity_keys[i] = public;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*
|
*
|
||||||
* Generic header file for ssh.
|
|
||||||
*
|
|
||||||
* As far as I am concerned, the code I have written for this software
|
* As far as I am concerned, the code I have written for this software
|
||||||
* can be used freely for any purpose. Any derived versions of this
|
* can be used freely for any purpose. Any derived versions of this
|
||||||
* software must be clearly marked as such, and if the derived work is
|
* software must be clearly marked as such, and if the derived work is
|
||||||
@ -12,15 +10,12 @@
|
|||||||
* called by a name other than "ssh" or "Secure Shell".
|
* called by a name other than "ssh" or "Secure Shell".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* RCSID("$OpenBSD: ssh.h,v 1.54 2000/10/11 20:27:24 markus Exp $"); */
|
/* RCSID("$OpenBSD: ssh.h,v 1.62 2001/01/23 10:45:10 markus Exp $"); */
|
||||||
/* $FreeBSD$ */
|
/* RCSID("$FreeBSD$"); */
|
||||||
|
|
||||||
#ifndef SSH_H
|
#ifndef SSH_H
|
||||||
#define SSH_H
|
#define SSH_H
|
||||||
|
|
||||||
#include "rsa.h"
|
|
||||||
#include "cipher.h"
|
|
||||||
|
|
||||||
/* Cipher used for encrypting authentication files. */
|
/* Cipher used for encrypting authentication files. */
|
||||||
#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
|
#define SSH_AUTHFILE_CIPHER SSH_CIPHER_3DES
|
||||||
|
|
||||||
@ -56,95 +51,6 @@
|
|||||||
*/
|
*/
|
||||||
#define SSH_SERVICE_NAME "ssh"
|
#define SSH_SERVICE_NAME "ssh"
|
||||||
|
|
||||||
#define ETCDIR "/etc/ssh"
|
|
||||||
#define PIDDIR "/var/run"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* System-wide file containing host keys of known hosts. This file should be
|
|
||||||
* world-readable.
|
|
||||||
*/
|
|
||||||
#define SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts"
|
|
||||||
#define SSH_SYSTEM_HOSTFILE2 ETCDIR "/ssh_known_hosts2"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Of these, ssh_host_key must be readable only by root, whereas ssh_config
|
|
||||||
* should be world-readable.
|
|
||||||
*/
|
|
||||||
#define HOST_KEY_FILE ETCDIR "/ssh_host_key"
|
|
||||||
#define SERVER_CONFIG_FILE ETCDIR "/sshd_config"
|
|
||||||
#define HOST_CONFIG_FILE ETCDIR "/ssh_config"
|
|
||||||
#define HOST_DSA_KEY_FILE ETCDIR "/ssh_host_dsa_key"
|
|
||||||
#define DH_PRIMES ETCDIR "/primes"
|
|
||||||
|
|
||||||
#define SSH_PROGRAM "/usr/bin/ssh"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The process id of the daemon listening for connections is saved here to
|
|
||||||
* make it easier to kill the correct daemon when necessary.
|
|
||||||
*/
|
|
||||||
#define SSH_DAEMON_PID_FILE PIDDIR "/sshd.pid"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The directory in user\'s home directory in which the files reside. The
|
|
||||||
* directory should be world-readable (though not all files are).
|
|
||||||
*/
|
|
||||||
#define SSH_USER_DIR ".ssh"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Per-user file containing host keys of known hosts. This file need not be
|
|
||||||
* readable by anyone except the user him/herself, though this does not
|
|
||||||
* contain anything particularly secret.
|
|
||||||
*/
|
|
||||||
#define SSH_USER_HOSTFILE "~/.ssh/known_hosts"
|
|
||||||
#define SSH_USER_HOSTFILE2 "~/.ssh/known_hosts2"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Name of the default file containing client-side authentication key. This
|
|
||||||
* file should only be readable by the user him/herself.
|
|
||||||
*/
|
|
||||||
#define SSH_CLIENT_IDENTITY ".ssh/identity"
|
|
||||||
#define SSH_CLIENT_ID_DSA ".ssh/id_dsa"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Configuration file in user\'s home directory. This file need not be
|
|
||||||
* readable by anyone but the user him/herself, but does not contain anything
|
|
||||||
* particularly secret. If the user\'s home directory resides on an NFS
|
|
||||||
* volume where root is mapped to nobody, this may need to be world-readable.
|
|
||||||
*/
|
|
||||||
#define SSH_USER_CONFFILE ".ssh/config"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* File containing a list of those rsa keys that permit logging in as this
|
|
||||||
* user. This file need not be readable by anyone but the user him/herself,
|
|
||||||
* but does not contain anything particularly secret. If the user\'s home
|
|
||||||
* directory resides on an NFS volume where root is mapped to nobody, this
|
|
||||||
* may need to be world-readable. (This file is read by the daemon which is
|
|
||||||
* running as root.)
|
|
||||||
*/
|
|
||||||
#define SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys"
|
|
||||||
#define SSH_USER_PERMITTED_KEYS2 ".ssh/authorized_keys2"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Per-user and system-wide ssh "rc" files. These files are executed with
|
|
||||||
* /bin/sh before starting the shell or command if they exist. They will be
|
|
||||||
* passed "proto cookie" as arguments if X11 forwarding with spoofing is in
|
|
||||||
* use. xauth will be run if neither of these exists.
|
|
||||||
*/
|
|
||||||
#define SSH_USER_RC ".ssh/rc"
|
|
||||||
#define SSH_SYSTEM_RC ETCDIR "/sshrc"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ssh-only version of /etc/hosts.equiv. Additionally, the daemon may use
|
|
||||||
* ~/.rhosts and /etc/hosts.equiv if rhosts authentication is enabled.
|
|
||||||
*/
|
|
||||||
#define SSH_HOSTS_EQUIV ETCDIR "/shosts.equiv"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Name of the environment variable containing the pathname of the
|
|
||||||
* authentication socket.
|
|
||||||
*/
|
|
||||||
#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Name of the environment variable containing the pathname of the
|
* Name of the environment variable containing the pathname of the
|
||||||
* authentication socket.
|
* authentication socket.
|
||||||
@ -152,10 +58,14 @@
|
|||||||
#define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID"
|
#define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Default path to ssh-askpass used by ssh-add,
|
* Name of the environment variable containing the pathname of the
|
||||||
* environment variable for overwriting the default location
|
* authentication socket.
|
||||||
|
*/
|
||||||
|
#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Environment variable for overwriting the default location of askpass
|
||||||
*/
|
*/
|
||||||
#define SSH_ASKPASS_DEFAULT "/usr/X11R6/bin/ssh-askpass"
|
|
||||||
#define SSH_ASKPASS_ENV "SSH_ASKPASS"
|
#define SSH_ASKPASS_ENV "SSH_ASKPASS"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -173,361 +83,9 @@
|
|||||||
/* Name of Kerberos service for SSH to use. */
|
/* Name of Kerberos service for SSH to use. */
|
||||||
#define KRB4_SERVICE_NAME "rcmd"
|
#define KRB4_SERVICE_NAME "rcmd"
|
||||||
|
|
||||||
/*
|
|
||||||
* Authentication methods. New types can be added, but old types should not
|
|
||||||
* be removed for compatibility. The maximum allowed value is 31.
|
|
||||||
*/
|
|
||||||
#define SSH_AUTH_RHOSTS 1
|
|
||||||
#define SSH_AUTH_RSA 2
|
|
||||||
#define SSH_AUTH_PASSWORD 3
|
|
||||||
#define SSH_AUTH_RHOSTS_RSA 4
|
|
||||||
#define SSH_AUTH_TIS 5
|
|
||||||
#define SSH_AUTH_KERBEROS 6
|
|
||||||
#define SSH_PASS_KERBEROS_TGT 7
|
|
||||||
/* 8 to 15 are reserved */
|
|
||||||
#define SSH_PASS_AFS_TOKEN 21
|
|
||||||
|
|
||||||
/* Protocol flags. These are bit masks. */
|
|
||||||
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
|
|
||||||
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Definition of message types. New values can be added, but old values
|
|
||||||
* should not be removed or without careful consideration of the consequences
|
|
||||||
* for compatibility. The maximum value is 254; value 255 is reserved for
|
|
||||||
* future extension.
|
|
||||||
*/
|
|
||||||
/* Message name */ /* msg code */ /* arguments */
|
|
||||||
#define SSH_MSG_NONE 0 /* no message */
|
|
||||||
#define SSH_MSG_DISCONNECT 1 /* cause (string) */
|
|
||||||
#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
|
|
||||||
#define SSH_CMSG_SESSION_KEY 3 /* key (BIGNUM) */
|
|
||||||
#define SSH_CMSG_USER 4 /* user (string) */
|
|
||||||
#define SSH_CMSG_AUTH_RHOSTS 5 /* user (string) */
|
|
||||||
#define SSH_CMSG_AUTH_RSA 6 /* modulus (BIGNUM) */
|
|
||||||
#define SSH_SMSG_AUTH_RSA_CHALLENGE 7 /* int (BIGNUM) */
|
|
||||||
#define SSH_CMSG_AUTH_RSA_RESPONSE 8 /* int (BIGNUM) */
|
|
||||||
#define SSH_CMSG_AUTH_PASSWORD 9 /* pass (string) */
|
|
||||||
#define SSH_CMSG_REQUEST_PTY 10 /* TERM, tty modes */
|
|
||||||
#define SSH_CMSG_WINDOW_SIZE 11 /* row,col,xpix,ypix */
|
|
||||||
#define SSH_CMSG_EXEC_SHELL 12 /* */
|
|
||||||
#define SSH_CMSG_EXEC_CMD 13 /* cmd (string) */
|
|
||||||
#define SSH_SMSG_SUCCESS 14 /* */
|
|
||||||
#define SSH_SMSG_FAILURE 15 /* */
|
|
||||||
#define SSH_CMSG_STDIN_DATA 16 /* data (string) */
|
|
||||||
#define SSH_SMSG_STDOUT_DATA 17 /* data (string) */
|
|
||||||
#define SSH_SMSG_STDERR_DATA 18 /* data (string) */
|
|
||||||
#define SSH_CMSG_EOF 19 /* */
|
|
||||||
#define SSH_SMSG_EXITSTATUS 20 /* status (int) */
|
|
||||||
#define SSH_MSG_CHANNEL_OPEN_CONFIRMATION 21 /* channel (int) */
|
|
||||||
#define SSH_MSG_CHANNEL_OPEN_FAILURE 22 /* channel (int) */
|
|
||||||
#define SSH_MSG_CHANNEL_DATA 23 /* ch,data (int,str) */
|
|
||||||
#define SSH_MSG_CHANNEL_CLOSE 24 /* channel (int) */
|
|
||||||
#define SSH_MSG_CHANNEL_CLOSE_CONFIRMATION 25 /* channel (int) */
|
|
||||||
/* SSH_CMSG_X11_REQUEST_FORWARDING 26 OBSOLETE */
|
|
||||||
#define SSH_SMSG_X11_OPEN 27 /* channel (int) */
|
|
||||||
#define SSH_CMSG_PORT_FORWARD_REQUEST 28 /* p,host,hp (i,s,i) */
|
|
||||||
#define SSH_MSG_PORT_OPEN 29 /* ch,h,p (i,s,i) */
|
|
||||||
#define SSH_CMSG_AGENT_REQUEST_FORWARDING 30 /* */
|
|
||||||
#define SSH_SMSG_AGENT_OPEN 31 /* port (int) */
|
|
||||||
#define SSH_MSG_IGNORE 32 /* string */
|
|
||||||
#define SSH_CMSG_EXIT_CONFIRMATION 33 /* */
|
|
||||||
#define SSH_CMSG_X11_REQUEST_FORWARDING 34 /* proto,data (s,s) */
|
|
||||||
#define SSH_CMSG_AUTH_RHOSTS_RSA 35 /* user,mod (s,mpi) */
|
|
||||||
#define SSH_MSG_DEBUG 36 /* string */
|
|
||||||
#define SSH_CMSG_REQUEST_COMPRESSION 37 /* level 1-9 (int) */
|
|
||||||
#define SSH_CMSG_MAX_PACKET_SIZE 38 /* size 4k-1024k (int) */
|
|
||||||
#define SSH_CMSG_AUTH_TIS 39 /* we use this for s/key */
|
|
||||||
#define SSH_SMSG_AUTH_TIS_CHALLENGE 40 /* challenge (string) */
|
|
||||||
#define SSH_CMSG_AUTH_TIS_RESPONSE 41 /* response (string) */
|
|
||||||
#define SSH_CMSG_AUTH_KERBEROS 42 /* (KTEXT) */
|
|
||||||
#define SSH_SMSG_AUTH_KERBEROS_RESPONSE 43 /* (KTEXT) */
|
|
||||||
#define SSH_CMSG_HAVE_KERBEROS_TGT 44
|
|
||||||
#define SSH_CMSG_HAVE_AFS_TOKEN 65 /* token (s) */
|
|
||||||
|
|
||||||
/* Kerberos IV tickets can't be forwarded. This is an AFS hack! */
|
/* Kerberos IV tickets can't be forwarded. This is an AFS hack! */
|
||||||
#define SSH_CMSG_HAVE_KRB4_TGT SSH_CMSG_HAVE_KERBEROS_TGT /* credentials (s) */
|
#define SSH_CMSG_HAVE_KRB4_TGT SSH_CMSG_HAVE_KERBEROS_TGT /* credentials (s) */
|
||||||
|
|
||||||
/*------------ definitions for login.c -------------*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the time when the user last logged in. Returns 0 if the
|
|
||||||
* information is not available. This must be called before record_login.
|
|
||||||
* The host from which the user logged in is stored in buf.
|
|
||||||
*/
|
|
||||||
unsigned long
|
|
||||||
get_last_login_time(uid_t uid, const char *logname,
|
|
||||||
char *buf, unsigned int bufsize);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Records that the user has logged in. This does many things normally done
|
|
||||||
* by login(1).
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
|
|
||||||
const char *host, struct sockaddr *addr);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Records that the user has logged out. This does many thigs normally done
|
|
||||||
* by login(1) or init.
|
|
||||||
*/
|
|
||||||
void record_logout(pid_t pid, const char *ttyname);
|
|
||||||
|
|
||||||
/*------------ definitions for sshconnect.c ----------*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Opens a TCP/IP connection to the remote server on the given host. If port
|
|
||||||
* is 0, the default port will be used. If anonymous is zero, a privileged
|
|
||||||
* port will be allocated to make the connection. This requires super-user
|
|
||||||
* privileges if anonymous is false. Connection_attempts specifies the
|
|
||||||
* maximum number of tries, one per second. This returns true on success,
|
|
||||||
* and zero on failure. If the connection is successful, this calls
|
|
||||||
* packet_set_connection for the connection.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
|
||||||
u_short port, int connection_attempts,
|
|
||||||
int anonymous, uid_t original_real_uid,
|
|
||||||
const char *proxy_command);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Starts a dialog with the server, and authenticates the current user on the
|
|
||||||
* server. This does not need any extra privileges. The basic connection to
|
|
||||||
* the server must already have been established before this is called. If
|
|
||||||
* login fails, this function prints an error and never returns. This
|
|
||||||
* initializes the random state, and leaves it initialized (it will also have
|
|
||||||
* references from the packet module).
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
ssh_login(int host_key_valid, RSA * host_key, const char *host,
|
|
||||||
struct sockaddr * hostaddr, uid_t original_real_uid);
|
|
||||||
|
|
||||||
/*------------ Definitions for various authentication methods. -------*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tries to authenticate the user using the .rhosts file. Returns true if
|
|
||||||
* authentication succeeds. If ignore_rhosts is non-zero, this will not
|
|
||||||
* consider .rhosts and .shosts (/etc/hosts.equiv will still be used).
|
|
||||||
*/
|
|
||||||
int auth_rhosts(struct passwd * pw, const char *client_user);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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, RSA* client_host_key);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Tries to authenticate the user using password. Returns true if
|
|
||||||
* authentication succeeds.
|
|
||||||
*/
|
|
||||||
int auth_password(struct passwd * pw, const char *password);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
|
|
||||||
* over the key. Skips any whitespace at the beginning and at end.
|
|
||||||
*/
|
|
||||||
int auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the name of the machine at the other end of the socket. The
|
|
||||||
* returned string should be freed by the caller.
|
|
||||||
*/
|
|
||||||
char *get_remote_hostname(int socket);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return the canonical name of the host in the other side of the current
|
|
||||||
* connection (as returned by packet_get_connection). The host name is
|
|
||||||
* cached, so it is efficient to call this several times.
|
|
||||||
*/
|
|
||||||
const char *get_canonical_hostname(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the local IP address as an ascii string.
|
|
||||||
*/
|
|
||||||
const char *get_ipaddr(int socket);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the remote IP address as an ascii string. The value need not be
|
|
||||||
* freed by the caller.
|
|
||||||
*/
|
|
||||||
const char *get_remote_ipaddr(void);
|
|
||||||
|
|
||||||
/* Returns the port number of the peer of the socket. */
|
|
||||||
int get_peer_port(int sock);
|
|
||||||
|
|
||||||
/* Returns the port number of the remote/local host. */
|
|
||||||
int get_remote_port(void);
|
|
||||||
int get_local_port(void);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Performs the RSA authentication challenge-response dialog with the client,
|
|
||||||
* and returns true (non-zero) if the client gave the correct answer to our
|
|
||||||
* challenge; returns zero if the client gives a wrong answer.
|
|
||||||
*/
|
|
||||||
int auth_rsa_challenge_dialog(RSA *pk);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reads a passphrase from /dev/tty with echo turned off. Returns the
|
|
||||||
* passphrase (allocated with xmalloc). Exits if EOF is encountered. If
|
|
||||||
* from_stdin is true, the passphrase will be read from stdin instead.
|
|
||||||
*/
|
|
||||||
char *read_passphrase(char *prompt, int from_stdin);
|
|
||||||
|
|
||||||
|
|
||||||
/*------------ Definitions for logging. -----------------------*/
|
|
||||||
|
|
||||||
/* Supported syslog facilities and levels. */
|
|
||||||
typedef enum {
|
|
||||||
SYSLOG_FACILITY_DAEMON,
|
|
||||||
SYSLOG_FACILITY_USER,
|
|
||||||
SYSLOG_FACILITY_AUTH,
|
|
||||||
SYSLOG_FACILITY_LOCAL0,
|
|
||||||
SYSLOG_FACILITY_LOCAL1,
|
|
||||||
SYSLOG_FACILITY_LOCAL2,
|
|
||||||
SYSLOG_FACILITY_LOCAL3,
|
|
||||||
SYSLOG_FACILITY_LOCAL4,
|
|
||||||
SYSLOG_FACILITY_LOCAL5,
|
|
||||||
SYSLOG_FACILITY_LOCAL6,
|
|
||||||
SYSLOG_FACILITY_LOCAL7
|
|
||||||
} SyslogFacility;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SYSLOG_LEVEL_QUIET,
|
|
||||||
SYSLOG_LEVEL_FATAL,
|
|
||||||
SYSLOG_LEVEL_ERROR,
|
|
||||||
SYSLOG_LEVEL_INFO,
|
|
||||||
SYSLOG_LEVEL_VERBOSE,
|
|
||||||
SYSLOG_LEVEL_DEBUG1,
|
|
||||||
SYSLOG_LEVEL_DEBUG2,
|
|
||||||
SYSLOG_LEVEL_DEBUG3
|
|
||||||
} LogLevel;
|
|
||||||
/* Initializes logging. */
|
|
||||||
void log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr);
|
|
||||||
|
|
||||||
/* Logging implementation, depending on server or client */
|
|
||||||
void do_log(LogLevel level, const char *fmt, va_list args);
|
|
||||||
|
|
||||||
/* name to facility/level */
|
|
||||||
SyslogFacility log_facility_number(char *name);
|
|
||||||
LogLevel log_level_number(char *name);
|
|
||||||
|
|
||||||
/* Output a message to syslog or stderr */
|
|
||||||
void fatal(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
|
||||||
void error(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
|
||||||
void log(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
|
||||||
void verbose(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
|
||||||
void debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
|
||||||
void debug2(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
|
||||||
void debug3(const char *fmt,...) __attribute__((format(printf, 1, 2)));
|
|
||||||
|
|
||||||
/* same as fatal() but w/o logging */
|
|
||||||
void fatal_cleanup(void);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Registers a cleanup function to be called by fatal()/fatal_cleanup()
|
|
||||||
* before exiting. It is permissible to call fatal_remove_cleanup for the
|
|
||||||
* function itself from the function.
|
|
||||||
*/
|
|
||||||
void fatal_add_cleanup(void (*proc) (void *context), void *context);
|
|
||||||
|
|
||||||
/* Removes a cleanup function to be called at fatal(). */
|
|
||||||
void fatal_remove_cleanup(void (*proc) (void *context), void *context);
|
|
||||||
|
|
||||||
/* ---- misc */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Expands tildes in the file name. Returns data allocated by xmalloc.
|
|
||||||
* Warning: this calls getpw*.
|
|
||||||
*/
|
|
||||||
char *tilde_expand_filename(const char *filename, uid_t my_uid);
|
|
||||||
|
|
||||||
/* remove newline at end of string */
|
|
||||||
char *chop(char *s);
|
|
||||||
|
|
||||||
/* return next token in configuration line */
|
|
||||||
char *strdelim(char **s);
|
|
||||||
|
|
||||||
/* set filedescriptor to non-blocking */
|
|
||||||
void set_nonblock(int fd);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Performs the interactive session. This handles data transmission between
|
|
||||||
* the client and the program. Note that the notion of stdin, stdout, and
|
|
||||||
* stderr in this function is sort of reversed: this function writes to stdin
|
|
||||||
* (of the child program), and reads from stdout and stderr (of the child
|
|
||||||
* program).
|
|
||||||
*/
|
|
||||||
void server_loop(pid_t pid, int fdin, int fdout, int fderr);
|
|
||||||
void server_loop2(void);
|
|
||||||
|
|
||||||
/* Client side main loop for the interactive session. */
|
|
||||||
int client_loop(int have_pty, int escape_char, int id);
|
|
||||||
|
|
||||||
/* Linked list of custom environment strings (see auth-rsa.c). */
|
|
||||||
struct envstring {
|
|
||||||
struct envstring *next;
|
|
||||||
char *s;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Ensure all of data on socket comes through. f==read || f==write
|
|
||||||
*/
|
|
||||||
ssize_t atomicio(ssize_t (*f)(), int fd, void *s, size_t n);
|
|
||||||
|
|
||||||
#ifdef KRB5
|
|
||||||
#include <krb5.h>
|
|
||||||
int auth_krb5(); /* XXX Doplnit prototypy */
|
|
||||||
int auth_krb5_tgt();
|
|
||||||
int krb5_init();
|
|
||||||
void krb5_cleanup_proc(void *ignore);
|
|
||||||
int auth_krb5_password(struct passwd *pw, const char *password);
|
|
||||||
#endif /* KRB5 */
|
|
||||||
|
|
||||||
#ifdef KRB4
|
|
||||||
#include <krb.h>
|
|
||||||
/*
|
|
||||||
* Performs Kerberos v4 mutual authentication 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_krb4(const char *server_user, KTEXT auth, char **client);
|
|
||||||
int krb4_init(uid_t uid);
|
|
||||||
void krb4_cleanup_proc(void *ignore);
|
|
||||||
int auth_krb4_password(struct passwd * pw, const char *password);
|
|
||||||
|
|
||||||
#ifdef AFS
|
|
||||||
#include <kafs.h>
|
|
||||||
|
|
||||||
/* Accept passed Kerberos v4 ticket-granting ticket and AFS tokens. */
|
|
||||||
int auth_krb4_tgt(struct passwd * pw, const char *string);
|
|
||||||
int auth_afs_token(struct passwd * pw, const char *token_string);
|
|
||||||
|
|
||||||
int creds_to_radix(CREDENTIALS * creds, unsigned char *buf, size_t buflen);
|
|
||||||
int radix_to_creds(const char *buf, CREDENTIALS * creds);
|
|
||||||
#endif /* AFS */
|
|
||||||
|
|
||||||
#endif /* KRB4 */
|
|
||||||
|
|
||||||
#ifdef SKEY
|
|
||||||
#include <opie.h>
|
|
||||||
char *skey_fake_keyinfo(char *username);
|
|
||||||
int auth_skey_password(struct passwd * pw, const char *password);
|
|
||||||
#endif /* SKEY */
|
|
||||||
|
|
||||||
/* AF_UNSPEC or AF_INET or AF_INET6 */
|
|
||||||
extern int IPv4or6;
|
|
||||||
|
|
||||||
#ifdef USE_PAM
|
#ifdef USE_PAM
|
||||||
#include "auth-pam.h"
|
#include "auth-pam.h"
|
||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
# defaults for users, and the values can be changed in per-user configuration
|
# defaults for users, and the values can be changed in per-user configuration
|
||||||
# files or on the command line.
|
# files or on the command line.
|
||||||
#
|
#
|
||||||
# $FreeBSD$
|
# $OpenBSD: ssh_config,v 1.10 2001/04/03 21:19:38 todd Exp $
|
||||||
|
# $FreeBSD$
|
||||||
|
|
||||||
|
# This is ssh client systemwide configuration file. See ssh(1) for more
|
||||||
|
# information. This file provides defaults for users, and the values can
|
||||||
|
# be changed in per-user configuration files or on the command line.
|
||||||
|
|
||||||
# Configuration data is parsed as follows:
|
# Configuration data is parsed as follows:
|
||||||
# 1. command line options
|
# 1. command line options
|
||||||
@ -15,9 +20,9 @@
|
|||||||
# Site-wide defaults for various options
|
# Site-wide defaults for various options
|
||||||
|
|
||||||
# Host *
|
# Host *
|
||||||
# ForwardAgent yes
|
# ForwardAgent no
|
||||||
# ForwardX11 yes
|
# ForwardX11 no
|
||||||
# RhostsAuthentication yes
|
# RhostsAuthentication no
|
||||||
# RhostsRSAAuthentication yes
|
# RhostsRSAAuthentication yes
|
||||||
# RSAAuthentication yes
|
# RSAAuthentication yes
|
||||||
# PasswordAuthentication yes
|
# PasswordAuthentication yes
|
||||||
@ -25,8 +30,10 @@
|
|||||||
# UseRsh no
|
# UseRsh no
|
||||||
# BatchMode no
|
# BatchMode no
|
||||||
# CheckHostIP yes
|
# CheckHostIP yes
|
||||||
# StrictHostKeyChecking no
|
# StrictHostKeyChecking yes
|
||||||
# IdentityFile ~/.ssh/identity
|
# IdentityFile ~/.ssh/identity
|
||||||
|
# IdentityFile ~/.ssh/id_dsa
|
||||||
|
# IdentityFile ~/.ssh/id_rsa
|
||||||
# Port 22
|
# Port 22
|
||||||
# Protocol 2,1
|
# Protocol 2,1
|
||||||
# Cipher blowfish
|
# Cipher blowfish
|
||||||
|
@ -13,24 +13,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: sshconnect.c,v 1.79 2000/09/17 15:52:51 markus Exp $");
|
RCSID("$OpenBSD: sshconnect.c,v 1.104 2001/04/12 19:15:25 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
|
|
||||||
|
#include "ssh.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "ssh.h"
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "readconf.h"
|
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "sshconnect.h"
|
#include "sshconnect.h"
|
||||||
#include "hostfile.h"
|
#include "hostfile.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "readconf.h"
|
||||||
|
#include "atomicio.h"
|
||||||
|
#include "misc.h"
|
||||||
|
|
||||||
char *client_version_string = NULL;
|
char *client_version_string = NULL;
|
||||||
char *server_version_string = NULL;
|
char *server_version_string = NULL;
|
||||||
@ -38,11 +39,14 @@ char *server_version_string = NULL;
|
|||||||
extern Options options;
|
extern Options options;
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
|
||||||
|
/* AF_UNSPEC or AF_INET or AF_INET6 */
|
||||||
|
extern int IPv4or6;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Connect to the given ssh server using a proxy command.
|
* Connect to the given ssh server using a proxy command.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
|
ssh_proxy_connect(const char *host, u_short port, struct passwd *pw,
|
||||||
const char *proxy_command)
|
const char *proxy_command)
|
||||||
{
|
{
|
||||||
Buffer command;
|
Buffer command;
|
||||||
@ -93,7 +97,7 @@ ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
|
|||||||
char *argv[10];
|
char *argv[10];
|
||||||
|
|
||||||
/* Child. Permanently give up superuser privileges. */
|
/* Child. Permanently give up superuser privileges. */
|
||||||
permanently_set_uid(original_real_uid);
|
permanently_set_uid(pw);
|
||||||
|
|
||||||
/* Redirect stdin and stdout. */
|
/* Redirect stdin and stdout. */
|
||||||
close(pin[1]);
|
close(pin[1]);
|
||||||
@ -110,15 +114,15 @@ ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
|
|||||||
|
|
||||||
/* Stderr is left as it is so that error messages get
|
/* Stderr is left as it is so that error messages get
|
||||||
printed on the user's terminal. */
|
printed on the user's terminal. */
|
||||||
argv[0] = "/bin/sh";
|
argv[0] = _PATH_BSHELL;
|
||||||
argv[1] = "-c";
|
argv[1] = "-c";
|
||||||
argv[2] = command_string;
|
argv[2] = command_string;
|
||||||
argv[3] = NULL;
|
argv[3] = NULL;
|
||||||
|
|
||||||
/* Execute the proxy command. Note that we gave up any
|
/* Execute the proxy command. Note that we gave up any
|
||||||
extra privileges above. */
|
extra privileges above. */
|
||||||
execv("/bin/sh", argv);
|
execv(argv[0], argv);
|
||||||
perror("/bin/sh");
|
perror(argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/* Parent. */
|
/* Parent. */
|
||||||
@ -142,7 +146,7 @@ ssh_proxy_connect(const char *host, u_short port, uid_t original_real_uid,
|
|||||||
* Creates a (possibly privileged) socket for use as the ssh connection.
|
* Creates a (possibly privileged) socket for use as the ssh connection.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ssh_create_socket(uid_t original_real_uid, int privileged, int family)
|
ssh_create_socket(struct passwd *pw, int privileged, int family)
|
||||||
{
|
{
|
||||||
int sock;
|
int sock;
|
||||||
|
|
||||||
@ -162,7 +166,7 @@ ssh_create_socket(uid_t original_real_uid, int privileged, int family)
|
|||||||
* Just create an ordinary socket on arbitrary port. We use
|
* Just create an ordinary socket on arbitrary port. We use
|
||||||
* the user's uid to create the socket.
|
* the user's uid to create the socket.
|
||||||
*/
|
*/
|
||||||
temporarily_use_uid(original_real_uid);
|
temporarily_use_uid(pw);
|
||||||
sock = socket(family, SOCK_STREAM, 0);
|
sock = socket(family, SOCK_STREAM, 0);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
error("socket: %.100s", strerror(errno));
|
error("socket: %.100s", strerror(errno));
|
||||||
@ -185,15 +189,16 @@ ssh_create_socket(uid_t original_real_uid, int privileged, int family)
|
|||||||
int
|
int
|
||||||
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
||||||
u_short port, int connection_attempts,
|
u_short port, int connection_attempts,
|
||||||
int anonymous, uid_t original_real_uid,
|
int anonymous, struct passwd *pw,
|
||||||
const char *proxy_command)
|
const char *proxy_command)
|
||||||
{
|
{
|
||||||
int sock = -1, attempt;
|
|
||||||
struct servent *sp;
|
|
||||||
struct addrinfo hints, *ai, *aitop;
|
|
||||||
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
|
||||||
int gaierr;
|
int gaierr;
|
||||||
|
int on = 1;
|
||||||
|
int sock = -1, attempt;
|
||||||
|
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
|
||||||
|
struct addrinfo hints, *ai, *aitop;
|
||||||
struct linger linger;
|
struct linger linger;
|
||||||
|
struct servent *sp;
|
||||||
|
|
||||||
debug("ssh_connect: getuid %u geteuid %u anon %d",
|
debug("ssh_connect: getuid %u geteuid %u anon %d",
|
||||||
(u_int) getuid(), (u_int) geteuid(), anonymous);
|
(u_int) getuid(), (u_int) geteuid(), anonymous);
|
||||||
@ -208,7 +213,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
|||||||
}
|
}
|
||||||
/* If a proxy command is given, connect using it. */
|
/* If a proxy command is given, connect using it. */
|
||||||
if (proxy_command != NULL)
|
if (proxy_command != NULL)
|
||||||
return ssh_proxy_connect(host, port, original_real_uid, proxy_command);
|
return ssh_proxy_connect(host, port, pw, proxy_command);
|
||||||
|
|
||||||
/* No proxy command. */
|
/* No proxy command. */
|
||||||
|
|
||||||
@ -244,8 +249,8 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
|||||||
host, ntop, strport);
|
host, ntop, strport);
|
||||||
|
|
||||||
/* Create a socket for connecting. */
|
/* Create a socket for connecting. */
|
||||||
sock = ssh_create_socket(original_real_uid,
|
sock = ssh_create_socket(pw,
|
||||||
!anonymous && geteuid() == 0 && port < IPPORT_RESERVED,
|
!anonymous && geteuid() == 0,
|
||||||
ai->ai_family);
|
ai->ai_family);
|
||||||
if (sock < 0)
|
if (sock < 0)
|
||||||
continue;
|
continue;
|
||||||
@ -254,10 +259,10 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
|||||||
* hope that it will help with tcp_wrappers showing
|
* hope that it will help with tcp_wrappers showing
|
||||||
* the remote uid as root.
|
* the remote uid as root.
|
||||||
*/
|
*/
|
||||||
temporarily_use_uid(original_real_uid);
|
temporarily_use_uid(pw);
|
||||||
if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
|
if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
|
||||||
/* Successful connection. */
|
/* Successful connection. */
|
||||||
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
|
memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
|
||||||
restore_uid();
|
restore_uid();
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@ -295,7 +300,13 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
|||||||
/* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
|
/* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
|
||||||
linger.l_onoff = 1;
|
linger.l_onoff = 1;
|
||||||
linger.l_linger = 5;
|
linger.l_linger = 5;
|
||||||
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
|
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
|
||||||
|
|
||||||
|
/* Set keepalives if requested. */
|
||||||
|
if (options.keepalives &&
|
||||||
|
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
|
||||||
|
sizeof(on)) < 0)
|
||||||
|
error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
|
||||||
|
|
||||||
/* Set the connection. */
|
/* Set the connection. */
|
||||||
packet_set_connection(sock, sock);
|
packet_set_connection(sock, sock);
|
||||||
@ -308,12 +319,13 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
|||||||
* identification string.
|
* identification string.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ssh_exchange_identification()
|
ssh_exchange_identification(void)
|
||||||
{
|
{
|
||||||
char buf[256], remote_version[256]; /* must be same size! */
|
char buf[256], remote_version[256]; /* must be same size! */
|
||||||
int remote_major, remote_minor, i, mismatch;
|
int remote_major, remote_minor, i, mismatch;
|
||||||
int connection_in = packet_get_connection_in();
|
int connection_in = packet_get_connection_in();
|
||||||
int connection_out = packet_get_connection_out();
|
int connection_out = packet_get_connection_out();
|
||||||
|
int minor1 = PROTOCOL_MINOR_1;
|
||||||
|
|
||||||
/* Read other side\'s version identification. */
|
/* Read other side\'s version identification. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -367,9 +379,10 @@ ssh_exchange_identification()
|
|||||||
}
|
}
|
||||||
if (remote_minor < 3) {
|
if (remote_minor < 3) {
|
||||||
fatal("Remote machine has too old SSH software version.");
|
fatal("Remote machine has too old SSH software version.");
|
||||||
} else if (remote_minor == 3) {
|
} else if (remote_minor == 3 || remote_minor == 4) {
|
||||||
/* We speak 1.3, too. */
|
/* We speak 1.3, too. */
|
||||||
enable_compat13();
|
enable_compat13();
|
||||||
|
minor1 = 3;
|
||||||
if (options.forward_agent) {
|
if (options.forward_agent) {
|
||||||
log("Agent forwarding disabled for protocol 1.3");
|
log("Agent forwarding disabled for protocol 1.3");
|
||||||
options.forward_agent = 0;
|
options.forward_agent = 0;
|
||||||
@ -395,7 +408,7 @@ ssh_exchange_identification()
|
|||||||
/* Send our own protocol version identification. */
|
/* Send our own protocol version identification. */
|
||||||
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
|
snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
|
||||||
compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
|
compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
|
||||||
compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1,
|
compat20 ? PROTOCOL_MINOR_2 : minor1,
|
||||||
SSH_VERSION);
|
SSH_VERSION);
|
||||||
if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
|
if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
|
||||||
fatal("write: %.100s", strerror(errno));
|
fatal("write: %.100s", strerror(errno));
|
||||||
@ -405,6 +418,7 @@ ssh_exchange_identification()
|
|||||||
debug("Local version string %.100s", client_version_string);
|
debug("Local version string %.100s", client_version_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* defaults to 'no' */
|
||||||
int
|
int
|
||||||
read_yes_or_no(const char *prompt, int defval)
|
read_yes_or_no(const char *prompt, int defval)
|
||||||
{
|
{
|
||||||
@ -412,10 +426,13 @@ read_yes_or_no(const char *prompt, int defval)
|
|||||||
FILE *f;
|
FILE *f;
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
||||||
if (isatty(0))
|
if (options.batch_mode)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (isatty(STDIN_FILENO))
|
||||||
f = stdin;
|
f = stdin;
|
||||||
else
|
else
|
||||||
f = fopen("/dev/tty", "rw");
|
f = fopen(_PATH_TTY, "rw");
|
||||||
|
|
||||||
if (f == NULL)
|
if (f == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
@ -461,11 +478,13 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
|||||||
Key *file_key;
|
Key *file_key;
|
||||||
char *type = key_type(host_key);
|
char *type = key_type(host_key);
|
||||||
char *ip = NULL;
|
char *ip = NULL;
|
||||||
char hostline[1000], *hostp;
|
char hostline[1000], *hostp, *fp;
|
||||||
HostStatus host_status;
|
HostStatus host_status;
|
||||||
HostStatus ip_status;
|
HostStatus ip_status;
|
||||||
int local = 0, host_ip_differ = 0;
|
int local = 0, host_ip_differ = 0;
|
||||||
char ntop[NI_MAXHOST];
|
char ntop[NI_MAXHOST];
|
||||||
|
int host_line, ip_line;
|
||||||
|
const char *host_file = NULL, *ip_file = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force accepting of the host key for loopback/localhost. The
|
* Force accepting of the host key for loopback/localhost. The
|
||||||
@ -487,23 +506,40 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
|||||||
local = 0;
|
local = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (local) {
|
if (local && options.host_key_alias == NULL) {
|
||||||
debug("Forcing accepting of host key for loopback/localhost.");
|
debug("Forcing accepting of host key for "
|
||||||
|
"loopback/localhost.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn off check_host_ip for proxy connects, since
|
* We don't have the remote ip-address for connections
|
||||||
* we don't have the remote ip-address
|
* using a proxy command
|
||||||
*/
|
*/
|
||||||
if (options.proxy_command != NULL && options.check_host_ip)
|
if (options.proxy_command == NULL) {
|
||||||
options.check_host_ip = 0;
|
|
||||||
|
|
||||||
if (options.check_host_ip) {
|
|
||||||
if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop),
|
if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop),
|
||||||
NULL, 0, NI_NUMERICHOST) != 0)
|
NULL, 0, NI_NUMERICHOST) != 0)
|
||||||
fatal("check_host_key: getnameinfo failed");
|
fatal("check_host_key: getnameinfo failed");
|
||||||
ip = xstrdup(ntop);
|
ip = xstrdup(ntop);
|
||||||
|
} else {
|
||||||
|
ip = xstrdup("<no hostip for proxy command>");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Turn off check_host_ip if the connection is to localhost, via proxy
|
||||||
|
* command or if we don't have a hostname to compare with
|
||||||
|
*/
|
||||||
|
if (options.check_host_ip &&
|
||||||
|
(local || strcmp(host, ip) == 0 || options.proxy_command != NULL))
|
||||||
|
options.check_host_ip = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow the user to record the key under a different name. This is
|
||||||
|
* useful for ssh tunneling over forwarded connections or if you run
|
||||||
|
* multiple sshd's on different ports on the same machine.
|
||||||
|
*/
|
||||||
|
if (options.host_key_alias != NULL) {
|
||||||
|
host = options.host_key_alias;
|
||||||
|
debug("using hostkeyalias: %s", host);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -516,19 +552,25 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
|||||||
* Check if the host key is present in the user\'s list of known
|
* Check if the host key is present in the user\'s list of known
|
||||||
* hosts or in the systemwide list.
|
* hosts or in the systemwide list.
|
||||||
*/
|
*/
|
||||||
host_status = check_host_in_hostfile(user_hostfile, host, host_key, file_key);
|
host_file = user_hostfile;
|
||||||
if (host_status == HOST_NEW)
|
host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line);
|
||||||
host_status = check_host_in_hostfile(system_hostfile, host, host_key, file_key);
|
if (host_status == HOST_NEW) {
|
||||||
|
host_file = system_hostfile;
|
||||||
|
host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Also perform check for the ip address, skip the check if we are
|
* Also perform check for the ip address, skip the check if we are
|
||||||
* localhost or the hostname was an ip address to begin with
|
* localhost or the hostname was an ip address to begin with
|
||||||
*/
|
*/
|
||||||
if (options.check_host_ip && !local && strcmp(host, ip)) {
|
if (options.check_host_ip) {
|
||||||
Key *ip_key = key_new(host_key->type);
|
Key *ip_key = key_new(host_key->type);
|
||||||
ip_status = check_host_in_hostfile(user_hostfile, ip, host_key, ip_key);
|
|
||||||
|
|
||||||
if (ip_status == HOST_NEW)
|
ip_file = user_hostfile;
|
||||||
ip_status = check_host_in_hostfile(system_hostfile, ip, host_key, ip_key);
|
ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line);
|
||||||
|
if (ip_status == HOST_NEW) {
|
||||||
|
ip_file = system_hostfile;
|
||||||
|
ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line);
|
||||||
|
}
|
||||||
if (host_status == HOST_CHANGED &&
|
if (host_status == HOST_CHANGED &&
|
||||||
(ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
|
(ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
|
||||||
host_ip_differ = 1;
|
host_ip_differ = 1;
|
||||||
@ -544,17 +586,14 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
|||||||
/* The host is known and the key matches. */
|
/* The host is known and the key matches. */
|
||||||
debug("Host '%.200s' is known and matches the %s host key.",
|
debug("Host '%.200s' is known and matches the %s host key.",
|
||||||
host, type);
|
host, type);
|
||||||
if (options.check_host_ip) {
|
debug("Found key in %s:%d", host_file, host_line);
|
||||||
if (ip_status == HOST_NEW) {
|
if (options.check_host_ip && ip_status == HOST_NEW) {
|
||||||
if (!add_host_to_hostfile(user_hostfile, ip, host_key))
|
if (!add_host_to_hostfile(user_hostfile, ip, host_key))
|
||||||
log("Failed to add the %s host key for IP address '%.30s' to the list of known hosts (%.30s).",
|
log("Failed to add the %s host key for IP address '%.128s' to the list of known hosts (%.30s).",
|
||||||
type, ip, user_hostfile);
|
type, ip, user_hostfile);
|
||||||
else
|
else
|
||||||
log("Warning: Permanently added the %s host key for IP address '%.30s' to the list of known hosts.",
|
log("Warning: Permanently added the %s host key for IP address '%.128s' to the list of known hosts.",
|
||||||
type, ip);
|
type, ip);
|
||||||
} else if (ip_status != HOST_OK)
|
|
||||||
log("Warning: the %s host key for '%.200s' differs from the key for the IP address '%.30s'",
|
|
||||||
type, host, ip);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HOST_NEW:
|
case HOST_NEW:
|
||||||
@ -566,16 +605,17 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
|||||||
} else if (options.strict_host_key_checking == 2) {
|
} else if (options.strict_host_key_checking == 2) {
|
||||||
/* The default */
|
/* The default */
|
||||||
char prompt[1024];
|
char prompt[1024];
|
||||||
char *fp = key_fingerprint(host_key);
|
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
|
||||||
snprintf(prompt, sizeof(prompt),
|
snprintf(prompt, sizeof(prompt),
|
||||||
"The authenticity of host '%.200s' can't be established.\n"
|
"The authenticity of host '%.200s (%s)' can't be established.\n"
|
||||||
"%s key fingerprint is %s.\n"
|
"%s key fingerprint is %s.\n"
|
||||||
"Are you sure you want to continue connecting (yes/no)? ",
|
"Are you sure you want to continue connecting (yes/no)? ",
|
||||||
host, type, fp);
|
host, ip, type, fp);
|
||||||
|
xfree(fp);
|
||||||
if (!read_yes_or_no(prompt, -1))
|
if (!read_yes_or_no(prompt, -1))
|
||||||
fatal("Aborted by user!\n");
|
fatal("Aborted by user!");
|
||||||
}
|
}
|
||||||
if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) {
|
if (options.check_host_ip && ip_status == HOST_NEW) {
|
||||||
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
|
snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
|
||||||
hostp = hostline;
|
hostp = hostline;
|
||||||
} else
|
} else
|
||||||
@ -605,18 +645,25 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
|||||||
error("and the key for the according IP address %s", ip);
|
error("and the key for the according IP address %s", ip);
|
||||||
error("%s. This could either mean that", msg);
|
error("%s. This could either mean that", msg);
|
||||||
error("DNS SPOOFING is happening or the IP address for the host");
|
error("DNS SPOOFING is happening or the IP address for the host");
|
||||||
error("and its host key have changed at the same time");
|
error("and its host key have changed at the same time.");
|
||||||
|
if (ip_status != HOST_NEW)
|
||||||
|
error("Offending key for IP in %s:%d", ip_file, ip_line);
|
||||||
}
|
}
|
||||||
/* The host key has changed. */
|
/* The host key has changed. */
|
||||||
|
fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
|
||||||
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
|
error("@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @");
|
||||||
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
||||||
error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
|
error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
|
||||||
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
|
error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
|
||||||
error("It is also possible that the %s host key has just been changed.", type);
|
error("It is also possible that the %s host key has just been changed.", type);
|
||||||
|
error("The fingerprint for the %s key sent by the remote host is\n%s.",
|
||||||
|
type, fp);
|
||||||
error("Please contact your system administrator.");
|
error("Please contact your system administrator.");
|
||||||
error("Add correct host key in %.100s to get rid of this message.",
|
error("Add correct host key in %.100s to get rid of this message.",
|
||||||
user_hostfile);
|
user_hostfile);
|
||||||
|
error("Offending key in %s:%d", host_file, host_line);
|
||||||
|
xfree(fp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If strict host key checking is in use, the user will have
|
* If strict host key checking is in use, the user will have
|
||||||
@ -638,6 +685,14 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
|||||||
error("Agent forwarding is disabled to avoid trojan horses.");
|
error("Agent forwarding is disabled to avoid trojan horses.");
|
||||||
options.forward_agent = 0;
|
options.forward_agent = 0;
|
||||||
}
|
}
|
||||||
|
if (options.forward_x11) {
|
||||||
|
error("X11 forwarding is disabled to avoid trojan horses.");
|
||||||
|
options.forward_x11 = 0;
|
||||||
|
}
|
||||||
|
if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) {
|
||||||
|
error("Port forwarding is disabled to avoid trojan horses.");
|
||||||
|
options.num_local_forwards = options.num_remote_forwards = 0;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* XXX Should permit the user to change to use the new id.
|
* XXX Should permit the user to change to use the new id.
|
||||||
* This could be done by converting the host key to an
|
* This could be done by converting the host key to an
|
||||||
@ -647,8 +702,25 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
|||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (options.check_host_ip)
|
|
||||||
xfree(ip);
|
if (options.check_host_ip && host_status != HOST_CHANGED &&
|
||||||
|
ip_status == HOST_CHANGED) {
|
||||||
|
log("Warning: the %s host key for '%.200s' "
|
||||||
|
"differs from the key for the IP address '%.128s'",
|
||||||
|
type, host, ip);
|
||||||
|
if (host_status == HOST_OK)
|
||||||
|
log("Matching host key in %s:%d", host_file, host_line);
|
||||||
|
log("Offending key for IP in %s:%d", ip_file, ip_line);
|
||||||
|
if (options.strict_host_key_checking == 1) {
|
||||||
|
fatal("Exiting, you have requested strict checking.");
|
||||||
|
} else if (options.strict_host_key_checking == 2) {
|
||||||
|
if (!read_yes_or_no("Are you sure you want " \
|
||||||
|
"to continue connecting (yes/no)? ", -1))
|
||||||
|
fatal("Aborted by user!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef KRB5
|
#ifdef KRB5
|
||||||
@ -857,17 +929,12 @@ send_krb5_tgt(krb5_context context, krb5_auth_context auth_context)
|
|||||||
* This function does not require super-user privileges.
|
* This function does not require super-user privileges.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
|
ssh_login(Key **keys, int nkeys, const char *orighost,
|
||||||
struct sockaddr *hostaddr, uid_t original_real_uid)
|
struct sockaddr *hostaddr, struct passwd *pw)
|
||||||
{
|
{
|
||||||
struct passwd *pw;
|
|
||||||
char *host, *cp;
|
char *host, *cp;
|
||||||
char *server_user, *local_user;
|
char *server_user, *local_user;
|
||||||
|
|
||||||
/* Get local user name. Use it as server user if no user name was given. */
|
|
||||||
pw = getpwuid(original_real_uid);
|
|
||||||
if (!pw)
|
|
||||||
fatal("User id %u not found from user database.", original_real_uid);
|
|
||||||
local_user = xstrdup(pw->pw_name);
|
local_user = xstrdup(pw->pw_name);
|
||||||
server_user = options.user ? options.user : local_user;
|
server_user = options.user ? options.user : local_user;
|
||||||
|
|
||||||
@ -887,10 +954,10 @@ ssh_login(int host_key_valid, RSA *own_host_key, const char *orighost,
|
|||||||
/* authenticate user */
|
/* authenticate user */
|
||||||
if (compat20) {
|
if (compat20) {
|
||||||
ssh_kex2(host, hostaddr);
|
ssh_kex2(host, hostaddr);
|
||||||
ssh_userauth2(server_user, host);
|
ssh_userauth2(local_user, server_user, host, keys, nkeys);
|
||||||
} else {
|
} else {
|
||||||
ssh_kex(host, hostaddr);
|
ssh_kex(host, hostaddr);
|
||||||
ssh_userauth(local_user, server_user, host, host_key_valid, own_host_key);
|
ssh_userauth1(local_user, server_user, host, keys, nkeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,6 +967,10 @@ ssh_put_password(char *password)
|
|||||||
int size;
|
int size;
|
||||||
char *padded;
|
char *padded;
|
||||||
|
|
||||||
|
if (datafellows & SSH_BUG_PASSWORDPAD) {
|
||||||
|
packet_put_string(password, strlen(password));
|
||||||
|
return;
|
||||||
|
}
|
||||||
size = roundup(strlen(password) + 1, 32);
|
size = roundup(strlen(password) + 1, 32);
|
||||||
padded = xmalloc(size);
|
padded = xmalloc(size);
|
||||||
memset(padded, 0, size);
|
memset(padded, 0, size);
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
/* $OpenBSD: sshconnect.h,v 1.9 2001/04/12 19:15:25 markus Exp $ */
|
||||||
|
/* $FreeBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
@ -20,23 +23,33 @@
|
|||||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
|
||||||
* $FreeBSD$
|
|
||||||
*/
|
*/
|
||||||
#ifndef SSHCONNECT_H
|
#ifndef SSHCONNECT_H
|
||||||
#define SSHCONNECT_H
|
#define SSHCONNECT_H
|
||||||
|
|
||||||
|
int
|
||||||
|
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
|
||||||
|
u_short port, int connection_attempts,
|
||||||
|
int anonymous, struct passwd *pw,
|
||||||
|
const char *proxy_command);
|
||||||
|
|
||||||
|
void
|
||||||
|
ssh_login(Key **keys, int nkeys, const char *orighost,
|
||||||
|
struct sockaddr *hostaddr, struct passwd *pw);
|
||||||
|
|
||||||
void
|
void
|
||||||
check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
|
||||||
const char *user_hostfile, const char *system_hostfile);
|
const char *user_hostfile, const char *system_hostfile);
|
||||||
|
|
||||||
void ssh_kex(char *host, struct sockaddr *hostaddr);
|
void ssh_kex(char *host, struct sockaddr *hostaddr);
|
||||||
void
|
|
||||||
ssh_userauth(const char* local_user, const char* server_user, char *host,
|
|
||||||
int host_key_valid, RSA *own_host_key);
|
|
||||||
|
|
||||||
void ssh_kex2(char *host, struct sockaddr *hostaddr);
|
void ssh_kex2(char *host, struct sockaddr *hostaddr);
|
||||||
void ssh_userauth2(const char *server_user, char *host);
|
|
||||||
|
void
|
||||||
|
ssh_userauth1(const char *local_user, const char *server_user, char *host,
|
||||||
|
Key **keys, int nkeys);
|
||||||
|
void
|
||||||
|
ssh_userauth2(const char *local_user, const char *server_user, char *host,
|
||||||
|
Key **keys, int nkeys);
|
||||||
|
|
||||||
void ssh_put_password(char *password);
|
void ssh_put_password(char *password);
|
||||||
|
|
||||||
|
@ -13,30 +13,41 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: sshconnect1.c,v 1.8 2000/10/12 09:59:19 markus Exp $");
|
RCSID("$OpenBSD: sshconnect1.c,v 1.31 2001/04/17 08:14:01 markus Exp $");
|
||||||
RCSID("$FreeBSD$");
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#ifdef KRB4
|
||||||
|
#include <krb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef AFS
|
||||||
|
#include <kafs.h>
|
||||||
|
#include "radix.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ssh.h"
|
||||||
|
#include "ssh1.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
#include "rsa.h"
|
#include "rsa.h"
|
||||||
#include "ssh.h"
|
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "mpaux.h"
|
#include "mpaux.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
|
#include "log.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "key.h"
|
#include "key.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
#include "sshconnect.h"
|
#include "sshconnect.h"
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
|
#include "readpass.h"
|
||||||
|
#include "cipher.h"
|
||||||
|
#include "canohost.h"
|
||||||
|
|
||||||
/* Session id for the current session. */
|
/* Session id for the current session. */
|
||||||
unsigned char session_id[16];
|
u_char session_id[16];
|
||||||
unsigned int supported_authentications = 0;
|
u_int supported_authentications = 0;
|
||||||
|
|
||||||
extern Options options;
|
extern Options options;
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
@ -46,13 +57,13 @@ extern char *__progname;
|
|||||||
* authenticate using the agent.
|
* authenticate using the agent.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
try_agent_authentication()
|
try_agent_authentication(void)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
char *comment;
|
char *comment;
|
||||||
AuthenticationConnection *auth;
|
AuthenticationConnection *auth;
|
||||||
unsigned char response[16];
|
u_char response[16];
|
||||||
unsigned int i;
|
u_int i;
|
||||||
int plen, clen;
|
int plen, clen;
|
||||||
Key *key;
|
Key *key;
|
||||||
BIGNUM *challenge;
|
BIGNUM *challenge;
|
||||||
@ -63,7 +74,6 @@ try_agent_authentication()
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
challenge = BN_new();
|
challenge = BN_new();
|
||||||
key = key_new(KEY_RSA);
|
|
||||||
|
|
||||||
/* Loop through identities served by the agent. */
|
/* Loop through identities served by the agent. */
|
||||||
for (key = ssh_get_first_identity(auth, &comment, 1);
|
for (key = ssh_get_first_identity(auth, &comment, 1);
|
||||||
@ -126,6 +136,7 @@ try_agent_authentication()
|
|||||||
|
|
||||||
/* The server returns success if it accepted the authentication. */
|
/* The server returns success if it accepted the authentication. */
|
||||||
if (type == SSH_SMSG_SUCCESS) {
|
if (type == SSH_SMSG_SUCCESS) {
|
||||||
|
ssh_close_authentication_connection(auth);
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
debug("RSA authentication accepted by server.");
|
debug("RSA authentication accepted by server.");
|
||||||
return 1;
|
return 1;
|
||||||
@ -135,6 +146,7 @@ try_agent_authentication()
|
|||||||
packet_disconnect("Protocol error waiting RSA auth response: %d",
|
packet_disconnect("Protocol error waiting RSA auth response: %d",
|
||||||
type);
|
type);
|
||||||
}
|
}
|
||||||
|
ssh_close_authentication_connection(auth);
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
debug("RSA authentication using agent refused.");
|
debug("RSA authentication using agent refused.");
|
||||||
return 0;
|
return 0;
|
||||||
@ -147,7 +159,7 @@ try_agent_authentication()
|
|||||||
void
|
void
|
||||||
respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
|
respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
|
||||||
{
|
{
|
||||||
unsigned char buf[32], response[16];
|
u_char buf[32], response[16];
|
||||||
MD5_CTX md;
|
MD5_CTX md;
|
||||||
int i, len;
|
int i, len;
|
||||||
|
|
||||||
@ -200,9 +212,9 @@ try_rsa_authentication(const char *authfile)
|
|||||||
int plen, clen;
|
int plen, clen;
|
||||||
|
|
||||||
/* Try to load identification for the authentication key. */
|
/* Try to load identification for the authentication key. */
|
||||||
public = key_new(KEY_RSA);
|
/* XXKEYLOAD */
|
||||||
if (!load_public_key(authfile, public, &comment)) {
|
public = key_load_public_type(KEY_RSA1, authfile, &comment);
|
||||||
key_free(public);
|
if (public == NULL) {
|
||||||
/* Could not load it. Fail. */
|
/* Could not load it. Fail. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -241,12 +253,12 @@ try_rsa_authentication(const char *authfile)
|
|||||||
|
|
||||||
debug("Received RSA challenge from server.");
|
debug("Received RSA challenge from server.");
|
||||||
|
|
||||||
private = key_new(KEY_RSA);
|
|
||||||
/*
|
/*
|
||||||
* Load the private key. Try first with empty passphrase; if it
|
* Load the private key. Try first with empty passphrase; if it
|
||||||
* fails, ask for a passphrase.
|
* fails, ask for a passphrase.
|
||||||
*/
|
*/
|
||||||
if (!load_private_key(authfile, "", private, NULL)) {
|
private = key_load_private_type(KEY_RSA1, authfile, "", NULL);
|
||||||
|
if (private == NULL) {
|
||||||
char buf[300];
|
char buf[300];
|
||||||
snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
|
snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
|
||||||
comment);
|
comment);
|
||||||
@ -259,7 +271,8 @@ try_rsa_authentication(const char *authfile)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Load the authentication file using the pasphrase. */
|
/* Load the authentication file using the pasphrase. */
|
||||||
if (!load_private_key(authfile, passphrase, private, NULL)) {
|
private = key_load_private_type(KEY_RSA1, authfile, passphrase, NULL);
|
||||||
|
if (private == NULL) {
|
||||||
memset(passphrase, 0, strlen(passphrase));
|
memset(passphrase, 0, strlen(passphrase));
|
||||||
xfree(passphrase);
|
xfree(passphrase);
|
||||||
error("Bad passphrase.");
|
error("Bad passphrase.");
|
||||||
@ -274,6 +287,7 @@ try_rsa_authentication(const char *authfile)
|
|||||||
/* Expect the server to reject it... */
|
/* Expect the server to reject it... */
|
||||||
packet_read_expect(&plen, SSH_SMSG_FAILURE);
|
packet_read_expect(&plen, SSH_SMSG_FAILURE);
|
||||||
xfree(comment);
|
xfree(comment);
|
||||||
|
BN_clear_free(challenge);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Destroy the passphrase. */
|
/* Destroy the passphrase. */
|
||||||
@ -309,7 +323,7 @@ try_rsa_authentication(const char *authfile)
|
|||||||
* authentication and RSA host authentication.
|
* authentication and RSA host authentication.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
|
try_rhosts_rsa_authentication(const char *local_user, Key * host_key)
|
||||||
{
|
{
|
||||||
int type;
|
int type;
|
||||||
BIGNUM *challenge;
|
BIGNUM *challenge;
|
||||||
@ -320,9 +334,9 @@ try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
|
|||||||
/* Tell the server that we are willing to authenticate using this key. */
|
/* Tell the server that we are willing to authenticate using this key. */
|
||||||
packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
|
packet_start(SSH_CMSG_AUTH_RHOSTS_RSA);
|
||||||
packet_put_string(local_user, strlen(local_user));
|
packet_put_string(local_user, strlen(local_user));
|
||||||
packet_put_int(BN_num_bits(host_key->n));
|
packet_put_int(BN_num_bits(host_key->rsa->n));
|
||||||
packet_put_bignum(host_key->e);
|
packet_put_bignum(host_key->rsa->e);
|
||||||
packet_put_bignum(host_key->n);
|
packet_put_bignum(host_key->rsa->n);
|
||||||
packet_send();
|
packet_send();
|
||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
|
|
||||||
@ -348,7 +362,7 @@ try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
|
|||||||
debug("Received RSA challenge for host key from server.");
|
debug("Received RSA challenge for host key from server.");
|
||||||
|
|
||||||
/* Compute a response to the challenge. */
|
/* Compute a response to the challenge. */
|
||||||
respond_to_rsa_challenge(challenge, host_key);
|
respond_to_rsa_challenge(challenge, host_key->rsa);
|
||||||
|
|
||||||
/* We no longer need the challenge. */
|
/* We no longer need the challenge. */
|
||||||
BN_clear_free(challenge);
|
BN_clear_free(challenge);
|
||||||
@ -367,7 +381,7 @@ try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
|
|||||||
|
|
||||||
#ifdef KRB4
|
#ifdef KRB4
|
||||||
int
|
int
|
||||||
try_krb4_authentication()
|
try_krb4_authentication(void)
|
||||||
{
|
{
|
||||||
KTEXT_ST auth; /* Kerberos data */
|
KTEXT_ST auth; /* Kerberos data */
|
||||||
char *reply;
|
char *reply;
|
||||||
@ -386,11 +400,11 @@ try_krb4_authentication()
|
|||||||
if (stat(tkt_string(), &st) < 0)
|
if (stat(tkt_string(), &st) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
strncpy(inst, (char *) krb_get_phost(get_canonical_hostname()), INST_SZ);
|
strncpy(inst, (char *) krb_get_phost(get_canonical_hostname(1)), INST_SZ);
|
||||||
|
|
||||||
realm = (char *) krb_realmofhost(get_canonical_hostname());
|
realm = (char *) krb_realmofhost(get_canonical_hostname(1));
|
||||||
if (!realm) {
|
if (!realm) {
|
||||||
debug("Kerberos V4: no realm for %s", get_canonical_hostname());
|
debug("Kerberos V4: no realm for %s", get_canonical_hostname(1));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* This can really be anything. */
|
/* This can really be anything. */
|
||||||
@ -445,7 +459,7 @@ try_krb4_authentication()
|
|||||||
debug("Kerberos V4 authentication accepted.");
|
debug("Kerberos V4 authentication accepted.");
|
||||||
|
|
||||||
/* Get server's response. */
|
/* Get server's response. */
|
||||||
reply = packet_get_string((unsigned int *) &auth.length);
|
reply = packet_get_string((u_int *) &auth.length);
|
||||||
memcpy(auth.dat, reply, auth.length);
|
memcpy(auth.dat, reply, auth.length);
|
||||||
xfree(reply);
|
xfree(reply);
|
||||||
|
|
||||||
@ -484,7 +498,7 @@ try_krb4_authentication()
|
|||||||
|
|
||||||
#ifdef AFS
|
#ifdef AFS
|
||||||
int
|
int
|
||||||
send_krb4_tgt()
|
send_krb4_tgt(void)
|
||||||
{
|
{
|
||||||
CREDENTIALS *creds;
|
CREDENTIALS *creds;
|
||||||
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
|
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
|
||||||
@ -510,7 +524,7 @@ send_krb4_tgt()
|
|||||||
debug("Kerberos V4 ticket expired: %s", TKT_FILE);
|
debug("Kerberos V4 ticket expired: %s", TKT_FILE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
creds_to_radix(creds, (unsigned char *)buffer, sizeof buffer);
|
creds_to_radix(creds, (u_char *)buffer, sizeof buffer);
|
||||||
xfree(creds);
|
xfree(creds);
|
||||||
|
|
||||||
packet_start(SSH_CMSG_HAVE_KRB4_TGT);
|
packet_start(SSH_CMSG_HAVE_KRB4_TGT);
|
||||||
@ -549,10 +563,10 @@ send_afs_tokens(void)
|
|||||||
p = buf;
|
p = buf;
|
||||||
|
|
||||||
/* Get secret token. */
|
/* Get secret token. */
|
||||||
memcpy(&creds.ticket_st.length, p, sizeof(unsigned int));
|
memcpy(&creds.ticket_st.length, p, sizeof(u_int));
|
||||||
if (creds.ticket_st.length > MAX_KTXT_LEN)
|
if (creds.ticket_st.length > MAX_KTXT_LEN)
|
||||||
break;
|
break;
|
||||||
p += sizeof(unsigned int);
|
p += sizeof(u_int);
|
||||||
memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
|
memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
|
||||||
p += creds.ticket_st.length;
|
p += creds.ticket_st.length;
|
||||||
|
|
||||||
@ -578,7 +592,7 @@ send_afs_tokens(void)
|
|||||||
creds.pinst[0] = '\0';
|
creds.pinst[0] = '\0';
|
||||||
|
|
||||||
/* Encode token, ship it off. */
|
/* Encode token, ship it off. */
|
||||||
if (creds_to_radix(&creds, (unsigned char*) buffer, sizeof buffer) <= 0)
|
if (creds_to_radix(&creds, (u_char *) buffer, sizeof buffer) <= 0)
|
||||||
break;
|
break;
|
||||||
packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
|
packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
|
||||||
packet_put_string(buffer, strlen(buffer));
|
packet_put_string(buffer, strlen(buffer));
|
||||||
@ -603,14 +617,15 @@ send_afs_tokens(void)
|
|||||||
* Note that the client code is not tied to s/key or TIS.
|
* Note that the client code is not tied to s/key or TIS.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
try_skey_authentication()
|
try_challenge_reponse_authentication(void)
|
||||||
{
|
{
|
||||||
int type, i;
|
int type, i;
|
||||||
int payload_len;
|
int payload_len;
|
||||||
unsigned int clen;
|
u_int clen;
|
||||||
|
char prompt[1024];
|
||||||
char *challenge, *response;
|
char *challenge, *response;
|
||||||
|
|
||||||
debug("Doing skey authentication.");
|
debug("Doing challenge reponse authentication.");
|
||||||
|
|
||||||
/* request a challenge */
|
/* request a challenge */
|
||||||
packet_start(SSH_CMSG_AUTH_TIS);
|
packet_start(SSH_CMSG_AUTH_TIS);
|
||||||
@ -636,9 +651,36 @@ try_skey_authentication()
|
|||||||
xfree(challenge);
|
xfree(challenge);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
for (i = 0; i < options.number_of_password_prompts; i++) {
|
for (i = 0; i < options.number_of_password_prompts; i++) {
|
||||||
|
/* request a challenge */
|
||||||
|
packet_start(SSH_CMSG_AUTH_TIS);
|
||||||
|
packet_send();
|
||||||
|
packet_write_wait();
|
||||||
|
|
||||||
|
type = packet_read(&payload_len);
|
||||||
|
if (type != SSH_SMSG_FAILURE &&
|
||||||
|
type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
|
||||||
|
packet_disconnect("Protocol error: got %d in response "
|
||||||
|
"to SSH_CMSG_AUTH_TIS", type);
|
||||||
|
}
|
||||||
|
if (type != SSH_SMSG_AUTH_TIS_CHALLENGE) {
|
||||||
|
debug("No challenge.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
challenge = packet_get_string(&clen);
|
||||||
|
packet_integrity_check(payload_len, (4 + clen), type);
|
||||||
|
snprintf(prompt, sizeof prompt, "%s%s", challenge,
|
||||||
|
strchr(challenge, '\n') ? "" : "\nResponse: ");
|
||||||
|
xfree(challenge);
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
error("Permission denied, please try again.");
|
error("Permission denied, please try again.");
|
||||||
response = read_passphrase("Response: ", 0);
|
if (options.cipher == SSH_CIPHER_NONE)
|
||||||
|
log("WARNING: Encryption is disabled! "
|
||||||
|
"Reponse will be transmitted in clear text.");
|
||||||
|
response = read_passphrase(prompt, 0);
|
||||||
|
if (strcmp(response, "") == 0) {
|
||||||
|
xfree(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
|
packet_start(SSH_CMSG_AUTH_TIS_RESPONSE);
|
||||||
ssh_put_password(response);
|
ssh_put_password(response);
|
||||||
memset(response, 0, strlen(response));
|
memset(response, 0, strlen(response));
|
||||||
@ -650,7 +692,7 @@ try_skey_authentication()
|
|||||||
return 1;
|
return 1;
|
||||||
if (type != SSH_SMSG_FAILURE)
|
if (type != SSH_SMSG_FAILURE)
|
||||||
packet_disconnect("Protocol error: got %d in response "
|
packet_disconnect("Protocol error: got %d in response "
|
||||||
"to skey-auth-reponse", type);
|
"to SSH_CMSG_AUTH_TIS_RESPONSE", type);
|
||||||
}
|
}
|
||||||
/* failure */
|
/* failure */
|
||||||
return 0;
|
return 0;
|
||||||
@ -702,10 +744,10 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
|
|||||||
Key k;
|
Key k;
|
||||||
int bits, rbits;
|
int bits, rbits;
|
||||||
int ssh_cipher_default = SSH_CIPHER_3DES;
|
int ssh_cipher_default = SSH_CIPHER_3DES;
|
||||||
unsigned char session_key[SSH_SESSION_KEY_LENGTH];
|
u_char session_key[SSH_SESSION_KEY_LENGTH];
|
||||||
unsigned char cookie[8];
|
u_char cookie[8];
|
||||||
unsigned int supported_ciphers;
|
u_int supported_ciphers;
|
||||||
unsigned int server_flags, client_flags;
|
u_int server_flags, client_flags;
|
||||||
int payload_len, clen, sum_len = 0;
|
int payload_len, clen, sum_len = 0;
|
||||||
u_int32_t rand = 0;
|
u_int32_t rand = 0;
|
||||||
|
|
||||||
@ -764,7 +806,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
|
|||||||
packet_integrity_check(payload_len,
|
packet_integrity_check(payload_len,
|
||||||
8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
|
8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
|
||||||
SSH_SMSG_PUBLIC_KEY);
|
SSH_SMSG_PUBLIC_KEY);
|
||||||
k.type = KEY_RSA;
|
k.type = KEY_RSA1;
|
||||||
k.rsa = host_key;
|
k.rsa = host_key;
|
||||||
check_host_key(host, hostaddr, &k,
|
check_host_key(host, hostaddr, &k,
|
||||||
options.user_hostfile, options.system_hostfile);
|
options.user_hostfile, options.system_hostfile);
|
||||||
@ -837,13 +879,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
|
|||||||
RSA_free(public_key);
|
RSA_free(public_key);
|
||||||
RSA_free(host_key);
|
RSA_free(host_key);
|
||||||
|
|
||||||
if (options.cipher == SSH_CIPHER_ILLEGAL) {
|
if (options.cipher == SSH_CIPHER_NOT_SET) {
|
||||||
|
if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default))
|
||||||
|
options.cipher = ssh_cipher_default;
|
||||||
|
} else if (options.cipher == SSH_CIPHER_ILLEGAL ||
|
||||||
|
!(cipher_mask_ssh1(1) & (1 << options.cipher))) {
|
||||||
log("No valid SSH1 cipher, using %.100s instead.",
|
log("No valid SSH1 cipher, using %.100s instead.",
|
||||||
cipher_name(ssh_cipher_default));
|
cipher_name(ssh_cipher_default));
|
||||||
options.cipher = ssh_cipher_default;
|
options.cipher = ssh_cipher_default;
|
||||||
} else if (options.cipher == SSH_CIPHER_NOT_SET) {
|
|
||||||
if (cipher_mask_ssh1(1) & supported_ciphers & (1 << ssh_cipher_default))
|
|
||||||
options.cipher = ssh_cipher_default;
|
|
||||||
}
|
}
|
||||||
/* Check that the selected cipher is supported. */
|
/* Check that the selected cipher is supported. */
|
||||||
if (!(supported_ciphers & (1 << options.cipher)))
|
if (!(supported_ciphers & (1 << options.cipher)))
|
||||||
@ -892,17 +935,14 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
|
|||||||
* Authenticate user
|
* Authenticate user
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ssh_userauth(
|
ssh_userauth1(const char *local_user, const char *server_user, char *host,
|
||||||
const char* local_user,
|
Key **keys, int nkeys)
|
||||||
const char* server_user,
|
|
||||||
char *host,
|
|
||||||
int host_key_valid, RSA *own_host_key)
|
|
||||||
{
|
{
|
||||||
int i, type;
|
int i, type;
|
||||||
int payload_len;
|
int payload_len;
|
||||||
|
|
||||||
if (supported_authentications == 0)
|
if (supported_authentications == 0)
|
||||||
fatal("ssh_userauth: server supports no auth methods");
|
fatal("ssh_userauth1: server supports no auth methods");
|
||||||
|
|
||||||
/* Send the name of the user to log in as on the server. */
|
/* Send the name of the user to log in as on the server. */
|
||||||
packet_start(SSH_CMSG_USER);
|
packet_start(SSH_CMSG_USER);
|
||||||
@ -1011,9 +1051,12 @@ ssh_userauth(
|
|||||||
* authentication.
|
* authentication.
|
||||||
*/
|
*/
|
||||||
if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
|
if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
|
||||||
options.rhosts_rsa_authentication && host_key_valid) {
|
options.rhosts_rsa_authentication) {
|
||||||
if (try_rhosts_rsa_authentication(local_user, own_host_key))
|
for (i = 0; i < nkeys; i++) {
|
||||||
return;
|
if (keys[i] != NULL && keys[i]->type == KEY_RSA1 &&
|
||||||
|
try_rhosts_rsa_authentication(local_user, keys[i]))
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Try RSA authentication if the server supports it. */
|
/* Try RSA authentication if the server supports it. */
|
||||||
if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
|
if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
|
||||||
@ -1028,13 +1071,15 @@ ssh_userauth(
|
|||||||
|
|
||||||
/* Try RSA authentication for each identity. */
|
/* Try RSA authentication for each identity. */
|
||||||
for (i = 0; i < options.num_identity_files; i++)
|
for (i = 0; i < options.num_identity_files; i++)
|
||||||
if (try_rsa_authentication(options.identity_files[i]))
|
if (options.identity_keys[i] != NULL &&
|
||||||
|
options.identity_keys[i]->type == KEY_RSA1 &&
|
||||||
|
try_rsa_authentication(options.identity_files[i]))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Try skey authentication if the server supports it. */
|
/* Try challenge response authentication if the server supports it. */
|
||||||
if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
|
if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
|
||||||
options.skey_authentication && !options.batch_mode) {
|
options.challenge_reponse_authentication && !options.batch_mode) {
|
||||||
if (try_skey_authentication())
|
if (try_challenge_reponse_authentication())
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Try password authentication if the server supports it. */
|
/* Try password authentication if the server supports it. */
|
||||||
@ -1042,7 +1087,7 @@ ssh_userauth(
|
|||||||
options.password_authentication && !options.batch_mode) {
|
options.password_authentication && !options.batch_mode) {
|
||||||
char prompt[80];
|
char prompt[80];
|
||||||
|
|
||||||
snprintf(prompt, sizeof(prompt), "%.30s@%.40s's password: ",
|
snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
|
||||||
server_user, host);
|
server_user, host);
|
||||||
if (try_password_authentication(prompt))
|
if (try_password_authentication(prompt))
|
||||||
return;
|
return;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -10,9 +10,9 @@
|
|||||||
.\" incompatible with the protocol description in the RFC file, it must be
|
.\" incompatible with the protocol description in the RFC file, it must be
|
||||||
.\" called by a name other than "ssh" or "Secure Shell".
|
.\" called by a name other than "ssh" or "Secure Shell".
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
|
.\" Copyright (c) 1999,2000 Markus Friedl. All rights reserved.
|
||||||
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
|
.\" Copyright (c) 1999 Aaron Campbell. All rights reserved.
|
||||||
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
|
.\" Copyright (c) 1999 Theo de Raadt. All rights reserved.
|
||||||
.\"
|
.\"
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
.\" modification, are permitted provided that the following conditions
|
.\" modification, are permitted provided that the following conditions
|
||||||
@ -34,6 +34,7 @@
|
|||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
|
.\" $OpenBSD: sshd.8,v 1.120 2001/04/22 23:58:36 markus Exp $
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd September 25, 1999
|
.Dd September 25, 1999
|
||||||
@ -41,10 +42,10 @@
|
|||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm sshd
|
.Nm sshd
|
||||||
.Nd secure shell daemon
|
.Nd OpenSSH SSH daemon
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm sshd
|
.Nm sshd
|
||||||
.Op Fl diqQ46
|
.Op Fl deiqD46
|
||||||
.Op Fl b Ar bits
|
.Op Fl b Ar bits
|
||||||
.Op Fl f Ar config_file
|
.Op Fl f Ar config_file
|
||||||
.Op Fl g Ar login_grace_time
|
.Op Fl g Ar login_grace_time
|
||||||
@ -55,7 +56,7 @@
|
|||||||
.Op Fl V Ar client_protocol_id
|
.Op Fl V Ar client_protocol_id
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
(Secure Shell Daemon) is the daemon program for
|
(SSH Daemon) is the daemon program for
|
||||||
.Xr ssh 1 .
|
.Xr ssh 1 .
|
||||||
Together these programs replace rlogin and rsh, and
|
Together these programs replace rlogin and rsh, and
|
||||||
provide secure encrypted communications between two untrusted hosts
|
provide secure encrypted communications between two untrusted hosts
|
||||||
@ -135,9 +136,9 @@ Each host has a host-specific DSA key used to identify the host.
|
|||||||
However, when the daemon starts, it does not generate a server key.
|
However, when the daemon starts, it does not generate a server key.
|
||||||
Forward security is provided through a Diffie-Hellman key agreement.
|
Forward security is provided through a Diffie-Hellman key agreement.
|
||||||
This key agreement results in a shared session key.
|
This key agreement results in a shared session key.
|
||||||
The rest of the session is encrypted
|
.Pp
|
||||||
using a symmetric cipher, currently
|
The rest of the session is encrypted using a symmetric cipher, currently
|
||||||
Blowfish, 3DES or CAST128 in CBC mode or Arcfour.
|
128 bit AES, Blowfish, 3DES, CAST128, Arcfour, 192 bit AES, or 256 bit AES.
|
||||||
The client selects the encryption algorithm
|
The client selects the encryption algorithm
|
||||||
to use from those offered by the server.
|
to use from those offered by the server.
|
||||||
Additionally, session integrity is provided
|
Additionally, session integrity is provided
|
||||||
@ -145,8 +146,9 @@ through a cryptographic message authentication code
|
|||||||
(hmac-sha1 or hmac-md5).
|
(hmac-sha1 or hmac-md5).
|
||||||
.Pp
|
.Pp
|
||||||
Protocol version 2 provides a public key based
|
Protocol version 2 provides a public key based
|
||||||
user authentication method (DSAAuthentication)
|
user (PubkeyAuthentication) or
|
||||||
and conventional password authentication.
|
client host (HostbasedAuthentication) authentication method,
|
||||||
|
conventional password authentication and challenge response based methods.
|
||||||
.Pp
|
.Pp
|
||||||
.Ss Command execution and data forwarding
|
.Ss Command execution and data forwarding
|
||||||
.Pp
|
.Pp
|
||||||
@ -175,12 +177,15 @@ configuration file.
|
|||||||
.Pp
|
.Pp
|
||||||
.Nm
|
.Nm
|
||||||
rereads its configuration file when it receives a hangup signal,
|
rereads its configuration file when it receives a hangup signal,
|
||||||
.Dv SIGHUP .
|
.Dv SIGHUP ,
|
||||||
|
by executing itself with the name it was started as, ie.
|
||||||
|
.Pa /usr/sbin/sshd .
|
||||||
.Pp
|
.Pp
|
||||||
The options are as follows:
|
The options are as follows:
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Fl b Ar bits
|
.It Fl b Ar bits
|
||||||
Specifies the number of bits in the server key (default 768).
|
Specifies the number of bits in the ephemeral protocol version 1
|
||||||
|
server key (default 768).
|
||||||
.Pp
|
.Pp
|
||||||
.It Fl d
|
.It Fl d
|
||||||
Debug mode.
|
Debug mode.
|
||||||
@ -188,8 +193,12 @@ The server sends verbose debug output to the system
|
|||||||
log, and does not put itself in the background.
|
log, and does not put itself in the background.
|
||||||
The server also will not fork and will only process one connection.
|
The server also will not fork and will only process one connection.
|
||||||
This option is only intended for debugging for the server.
|
This option is only intended for debugging for the server.
|
||||||
Multiple -d options increases the debugging level.
|
Multiple -d options increase the debugging level.
|
||||||
Maximum is 3.
|
Maximum is 3.
|
||||||
|
.It Fl e
|
||||||
|
When this option is specified,
|
||||||
|
.Nm
|
||||||
|
will send the output to the standard error instead of the system log.
|
||||||
.It Fl f Ar configuration_file
|
.It Fl f Ar configuration_file
|
||||||
Specifies the name of the configuration file.
|
Specifies the name of the configuration file.
|
||||||
The default is
|
The default is
|
||||||
@ -198,17 +207,19 @@ The default is
|
|||||||
refuses to start if there is no configuration file.
|
refuses to start if there is no configuration file.
|
||||||
.It Fl g Ar login_grace_time
|
.It Fl g Ar login_grace_time
|
||||||
Gives the grace time for clients to authenticate themselves (default
|
Gives the grace time for clients to authenticate themselves (default
|
||||||
300 seconds).
|
600 seconds).
|
||||||
If the client fails to authenticate the user within
|
If the client fails to authenticate the user within
|
||||||
this many seconds, the server disconnects and exits.
|
this many seconds, the server disconnects and exits.
|
||||||
A value of zero indicates no limit.
|
A value of zero indicates no limit.
|
||||||
.It Fl h Ar host_key_file
|
.It Fl h Ar host_key_file
|
||||||
Specifies the file from which the RSA host key is read (default
|
Specifies the file from which the host key is read (default
|
||||||
.Pa /etc/ssh/ssh_host_key ) .
|
.Pa /etc/ssh/ssh_host_key ) .
|
||||||
This option must be given if
|
This option must be given if
|
||||||
.Nm
|
.Nm
|
||||||
is not run as root (as the normal
|
is not run as root (as the normal
|
||||||
host file is normally not readable by anyone but root).
|
host file is normally not readable by anyone but root).
|
||||||
|
It is possible to have multiple host key files for
|
||||||
|
the different protocol versions and host key algorithms.
|
||||||
.It Fl i
|
.It Fl i
|
||||||
Specifies that
|
Specifies that
|
||||||
.Nm
|
.Nm
|
||||||
@ -223,8 +234,8 @@ However, with small key sizes (e.g., 512) using
|
|||||||
from inetd may
|
from inetd may
|
||||||
be feasible.
|
be feasible.
|
||||||
.It Fl k Ar key_gen_time
|
.It Fl k Ar key_gen_time
|
||||||
Specifies how often the server key is regenerated (default 3600
|
Specifies how often the ephemeral protocol version 1 server key is
|
||||||
seconds, or one hour).
|
regenerated (default 3600 seconds, or one hour).
|
||||||
The motivation for regenerating the key fairly
|
The motivation for regenerating the key fairly
|
||||||
often is that the key is not stored anywhere, and after about an hour,
|
often is that the key is not stored anywhere, and after about an hour,
|
||||||
it becomes impossible to recover the key for decrypting intercepted
|
it becomes impossible to recover the key for decrypting intercepted
|
||||||
@ -255,16 +266,12 @@ indicates that only dotted decimal addresses
|
|||||||
should be put into the
|
should be put into the
|
||||||
.Pa utmp
|
.Pa utmp
|
||||||
file.
|
file.
|
||||||
.It Fl Q
|
.It Fl D
|
||||||
Do not print an error message if RSA support is missing.
|
|
||||||
.It Fl V Ar client_protocol_id
|
|
||||||
SSH-2 compatibility mode.
|
|
||||||
When this option is specified
|
When this option is specified
|
||||||
.Nm
|
.Nm
|
||||||
assumes the client has sent the supplied version string
|
will not detach and does not become a daemon.
|
||||||
and skips the
|
This allows easy monitoring of
|
||||||
Protocol Version Identification Exchange.
|
.Nm sshd .
|
||||||
This option is not intended to be called directly.
|
|
||||||
.It Fl 4
|
.It Fl 4
|
||||||
Forces
|
Forces
|
||||||
.Nm
|
.Nm
|
||||||
@ -293,17 +300,17 @@ Specifies whether an AFS token may be forwarded to the server.
|
|||||||
Default is
|
Default is
|
||||||
.Dq yes .
|
.Dq yes .
|
||||||
.It Cm AllowGroups
|
.It Cm AllowGroups
|
||||||
This keyword can be followed by a number of group names, separated
|
This keyword can be followed by a list of group names, separated
|
||||||
by spaces.
|
by spaces.
|
||||||
If specified, login is allowed only for users whose primary
|
If specified, login is allowed only for users whose primary
|
||||||
group matches one of the patterns.
|
group or supplementary group list matches one of the patterns.
|
||||||
.Ql \&*
|
.Ql \&*
|
||||||
and
|
and
|
||||||
.Ql ?
|
.Ql ?
|
||||||
can be used as
|
can be used as
|
||||||
wildcards in the patterns.
|
wildcards in the patterns.
|
||||||
Only group names are valid; a numerical group ID isn't recognized.
|
Only group names are valid; a numerical group ID isn't recognized.
|
||||||
By default login is allowed regardless of the primary group.
|
By default login is allowed regardless of the group list.
|
||||||
.Pp
|
.Pp
|
||||||
.It Cm AllowTcpForwarding
|
.It Cm AllowTcpForwarding
|
||||||
Specifies whether TCP forwarding is permitted.
|
Specifies whether TCP forwarding is permitted.
|
||||||
@ -314,7 +321,7 @@ users are also denied shell access, as they can always install their
|
|||||||
own forwarders.
|
own forwarders.
|
||||||
.Pp
|
.Pp
|
||||||
.It Cm AllowUsers
|
.It Cm AllowUsers
|
||||||
This keyword can be followed by a number of user names, separated
|
This keyword can be followed by a list of user names, separated
|
||||||
by spaces.
|
by spaces.
|
||||||
If specified, login is allowed only for users names that
|
If specified, login is allowed only for users names that
|
||||||
match one of the patterns.
|
match one of the patterns.
|
||||||
@ -326,29 +333,76 @@ wildcards in the patterns.
|
|||||||
Only user names are valid; a numerical user ID isn't recognized.
|
Only user names are valid; a numerical user ID isn't recognized.
|
||||||
By default login is allowed regardless of the user name.
|
By default login is allowed regardless of the user name.
|
||||||
.Pp
|
.Pp
|
||||||
|
.It Cm Banner
|
||||||
|
In some jurisdictions, sending a warning message before authentication
|
||||||
|
may be relevant for getting legal protection.
|
||||||
|
The contents of the specified file are sent to the remote user before
|
||||||
|
authentication is allowed.
|
||||||
|
This option is only available for protocol version 2.
|
||||||
|
.Pp
|
||||||
|
.It Cm ChallengeResponseAuthentication
|
||||||
|
Specifies whether
|
||||||
|
challenge response
|
||||||
|
authentication is allowed.
|
||||||
|
Currently there is only support for
|
||||||
|
.Xr skey 1
|
||||||
|
authentication.
|
||||||
|
The default is
|
||||||
|
.Dq yes .
|
||||||
.It Cm Ciphers
|
.It Cm Ciphers
|
||||||
Specifies the ciphers allowed for protocol version 2.
|
Specifies the ciphers allowed for protocol version 2.
|
||||||
Multiple ciphers must be comma-separated.
|
Multiple ciphers must be comma-separated.
|
||||||
The default is
|
The default is
|
||||||
.Dq 3des-cbc,blowfish-cbc,arcfour,cast128-cbc .
|
.Dq aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour.
|
||||||
.It Cm CheckMail
|
.It Cm CheckMail
|
||||||
Specifies whether
|
Specifies whether
|
||||||
.Nm
|
.Nm
|
||||||
should check for new mail for interactive logins.
|
should check for new mail for interactive logins.
|
||||||
The default is
|
The default is
|
||||||
.Dq yes .
|
.Dq yes .
|
||||||
|
.It Cm ClientAliveInterval
|
||||||
|
Sets a timeout interval in seconds after which if no data has been received
|
||||||
|
from the client,
|
||||||
|
.Nm
|
||||||
|
will send a message through the encrypted
|
||||||
|
channel to request a response from the client.
|
||||||
|
The default
|
||||||
|
is 0, indicating that these messages will not be sent to the client.
|
||||||
|
This option applies to protocol version 2 only.
|
||||||
|
.It Cm ClientAliveCountMax
|
||||||
|
Sets the number of client alive messages (see above) which may be
|
||||||
|
sent without
|
||||||
|
.Nm
|
||||||
|
receiving any messages back from the client. If this threshold is
|
||||||
|
reached while client alive messages are being sent,
|
||||||
|
.Nm
|
||||||
|
will disconnect the client, terminating the session. It is important
|
||||||
|
to note that the use of client alive messages is very different from
|
||||||
|
.Cm Keepalive
|
||||||
|
(below). The client alive messages are sent through the
|
||||||
|
encrypted channel and therefore will not be spoofable. The TCP keepalive
|
||||||
|
option enabled by
|
||||||
|
.Cm Keepalive
|
||||||
|
is spoofable. You want to use the client
|
||||||
|
alive mechanism when you are basing something important on
|
||||||
|
clients having an active connection to the server.
|
||||||
|
.Pp
|
||||||
|
The default value is 3. If you set
|
||||||
|
.Cm ClientAliveInterval
|
||||||
|
(above) to 15, and leave this value at the default, unresponsive ssh clients
|
||||||
|
will be disconnected after approximately 45 seconds.
|
||||||
.It Cm DenyGroups
|
.It Cm DenyGroups
|
||||||
This keyword can be followed by a number of group names, separated
|
This keyword can be followed by a number of group names, separated
|
||||||
by spaces.
|
by spaces.
|
||||||
Users whose primary group matches one of the patterns
|
Users whose primary group or supplementary group list matches
|
||||||
aren't allowed to log in.
|
one of the patterns aren't allowed to log in.
|
||||||
.Ql \&*
|
.Ql \&*
|
||||||
and
|
and
|
||||||
.Ql ?
|
.Ql ?
|
||||||
can be used as
|
can be used as
|
||||||
wildcards in the patterns.
|
wildcards in the patterns.
|
||||||
Only group names are valid; a numerical group ID isn't recognized.
|
Only group names are valid; a numerical group ID isn't recognized.
|
||||||
By default login is allowed regardless of the primary group.
|
By default login is allowed regardless of the group list.
|
||||||
.Pp
|
.Pp
|
||||||
.It Cm DenyUsers
|
.It Cm DenyUsers
|
||||||
This keyword can be followed by a number of user names, separated
|
This keyword can be followed by a number of user names, separated
|
||||||
@ -360,11 +414,6 @@ and
|
|||||||
can be used as wildcards in the patterns.
|
can be used as wildcards in the patterns.
|
||||||
Only user names are valid; a numerical user ID isn't recognized.
|
Only user names are valid; a numerical user ID isn't recognized.
|
||||||
By default login is allowed regardless of the user name.
|
By default login is allowed regardless of the user name.
|
||||||
.It Cm DSAAuthentication
|
|
||||||
Specifies whether DSA authentication is allowed.
|
|
||||||
The default is
|
|
||||||
.Dq yes .
|
|
||||||
Note that this option applies to protocol version 2 only.
|
|
||||||
.It Cm GatewayPorts
|
.It Cm GatewayPorts
|
||||||
Specifies whether remote hosts are allowed to connect to ports
|
Specifies whether remote hosts are allowed to connect to ports
|
||||||
forwarded for the client.
|
forwarded for the client.
|
||||||
@ -374,26 +423,40 @@ or
|
|||||||
.Dq no .
|
.Dq no .
|
||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
.It Cm HostDSAKey
|
.It Cm HostbasedAuthentication
|
||||||
Specifies the file containing the private DSA host key (default
|
Specifies whether rhosts or /etc/hosts.equiv authentication together
|
||||||
.Pa /etc/ssh/ssh_host_dsa_key )
|
with successful public key client host authentication is allowed
|
||||||
used by SSH protocol 2.0.
|
(hostbased authentication).
|
||||||
Note that
|
This option is similar to
|
||||||
.Nm
|
.Cm RhostsRSAAuthentication
|
||||||
disables protocol 2.0 if this file is group/world-accessible.
|
and applies to protocol version 2 only.
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
.It Cm HostKey
|
.It Cm HostKey
|
||||||
Specifies the file containing the private RSA host key (default
|
Specifies the file containing the private host keys (default
|
||||||
.Pa /etc/ssh/ssh_host_key )
|
.Pa /etc/ssh/ssh_host_key )
|
||||||
used by SSH protocols 1.3 and 1.5.
|
used by SSH protocol versions 1 and 2.
|
||||||
Note that
|
Note that
|
||||||
.Nm
|
.Nm
|
||||||
disables protocols 1.3 and 1.5 if this file is group/world-accessible.
|
will refuse to use a file if it is group/world-accessible.
|
||||||
|
It is possible to have multiple host key files.
|
||||||
|
.Dq rsa1
|
||||||
|
keys are used for version 1 and
|
||||||
|
.Dq dsa
|
||||||
|
or
|
||||||
|
.Dq rsa
|
||||||
|
are used for version 2 of the SSH protocol.
|
||||||
.It Cm IgnoreRhosts
|
.It Cm IgnoreRhosts
|
||||||
Specifies that
|
Specifies that
|
||||||
.Pa .rhosts
|
.Pa .rhosts
|
||||||
and
|
and
|
||||||
.Pa .shosts
|
.Pa .shosts
|
||||||
files will not be used in authentication.
|
files will not be used in
|
||||||
|
.Cm RhostsAuthentication ,
|
||||||
|
.Cm RhostsRSAAuthentication
|
||||||
|
or
|
||||||
|
.Cm HostbasedAuthentication .
|
||||||
|
.Pp
|
||||||
.Pa /etc/hosts.equiv
|
.Pa /etc/hosts.equiv
|
||||||
and
|
and
|
||||||
.Pa /etc/ssh/shosts.equiv
|
.Pa /etc/ssh/shosts.equiv
|
||||||
@ -406,7 +469,9 @@ Specifies whether
|
|||||||
should ignore the user's
|
should ignore the user's
|
||||||
.Pa $HOME/.ssh/known_hosts
|
.Pa $HOME/.ssh/known_hosts
|
||||||
during
|
during
|
||||||
.Cm RhostsRSAAuthentication .
|
.Cm RhostsRSAAuthentication
|
||||||
|
or
|
||||||
|
.Cm HostbasedAuthentication .
|
||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
.It Cm KeepAlive
|
.It Cm KeepAlive
|
||||||
@ -459,8 +524,8 @@ file on logout.
|
|||||||
Default is
|
Default is
|
||||||
.Dq yes .
|
.Dq yes .
|
||||||
.It Cm KeyRegenerationInterval
|
.It Cm KeyRegenerationInterval
|
||||||
The server key is automatically regenerated after this many seconds
|
In protocol version 1, the ephemeral server key is automatically regenerated
|
||||||
(if it has been used).
|
after this many seconds (if it has been used).
|
||||||
The purpose of regeneration is to prevent
|
The purpose of regeneration is to prevent
|
||||||
decrypting captured sessions by later breaking into the machine and
|
decrypting captured sessions by later breaking into the machine and
|
||||||
stealing the keys.
|
stealing the keys.
|
||||||
@ -468,14 +533,42 @@ The key is never stored anywhere.
|
|||||||
If the value is 0, the key is never regenerated.
|
If the value is 0, the key is never regenerated.
|
||||||
The default is 3600 (seconds).
|
The default is 3600 (seconds).
|
||||||
.It Cm ListenAddress
|
.It Cm ListenAddress
|
||||||
Specifies what local address
|
Specifies the local addresses
|
||||||
.Nm
|
.Nm
|
||||||
should listen on.
|
should listen on.
|
||||||
The default is to listen to all local addresses.
|
The following forms may be used:
|
||||||
Multiple options of this type are permitted.
|
.Pp
|
||||||
Additionally, the
|
.Bl -item -offset indent -compact
|
||||||
.Cm Ports
|
.It
|
||||||
options must precede this option.
|
.Cm ListenAddress
|
||||||
|
.Sm off
|
||||||
|
.Ar host No | Ar IPv4_addr No | Ar IPv6_addr
|
||||||
|
.Sm on
|
||||||
|
.It
|
||||||
|
.Cm ListenAddress
|
||||||
|
.Sm off
|
||||||
|
.Ar host No | Ar IPv4_addr No : Ar port
|
||||||
|
.Sm on
|
||||||
|
.It
|
||||||
|
.Cm ListenAddress
|
||||||
|
.Sm off
|
||||||
|
.Oo
|
||||||
|
.Ar host No | Ar IPv6_addr Oc : Ar port
|
||||||
|
.Sm on
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If
|
||||||
|
.Ar port
|
||||||
|
is not specified,
|
||||||
|
.Nm
|
||||||
|
will listen on the address and all prior
|
||||||
|
.Cm Port
|
||||||
|
options specified. The default is to listen on all local
|
||||||
|
addresses. Multiple
|
||||||
|
.Cm ListenAddress
|
||||||
|
options are permitted. Additionally, any
|
||||||
|
.Cm Port
|
||||||
|
options must precede this option for non port qualified addresses.
|
||||||
.It Cm LoginGraceTime
|
.It Cm LoginGraceTime
|
||||||
The server disconnects after this time if the user has not
|
The server disconnects after this time if the user has not
|
||||||
successfully logged in.
|
successfully logged in.
|
||||||
@ -489,6 +582,17 @@ QUIET, FATAL, ERROR, INFO, VERBOSE and DEBUG.
|
|||||||
The default is INFO.
|
The default is INFO.
|
||||||
Logging with level DEBUG violates the privacy of users
|
Logging with level DEBUG violates the privacy of users
|
||||||
and is not recommended.
|
and is not recommended.
|
||||||
|
.It Cm MACs
|
||||||
|
Specifies the available MAC (message authentication code) algorithms.
|
||||||
|
The MAC algorithm is used in protocol version 2
|
||||||
|
for data integrity protection.
|
||||||
|
Multiple algorithms must be comma-separated.
|
||||||
|
The default is
|
||||||
|
.Pp
|
||||||
|
.Bd -literal
|
||||||
|
``hmac-md5,hmac-sha1,hmac-ripemd160,hmac-ripemd160@openssh.com,
|
||||||
|
hmac-sha1-96,hmac-md5-96''
|
||||||
|
.Ed
|
||||||
.It Cm MaxStartups
|
.It Cm MaxStartups
|
||||||
Specifies the maximum number of concurrent unauthenticated connections to the
|
Specifies the maximum number of concurrent unauthenticated connections to the
|
||||||
.Nm
|
.Nm
|
||||||
@ -503,14 +607,14 @@ the three colon separated values
|
|||||||
.Dq start:rate:full
|
.Dq start:rate:full
|
||||||
(e.g., "10:30:60").
|
(e.g., "10:30:60").
|
||||||
.Nm
|
.Nm
|
||||||
will refuse connection attempts with a probabillity of
|
will refuse connection attempts with a probability of
|
||||||
.Dq rate/100
|
.Dq rate/100
|
||||||
(30%)
|
(30%)
|
||||||
if there are currently
|
if there are currently
|
||||||
.Dq start
|
.Dq start
|
||||||
(10)
|
(10)
|
||||||
unauthenticated connections.
|
unauthenticated connections.
|
||||||
The probabillity increases linearly and all connection attempts
|
The probability increases linearly and all connection attempts
|
||||||
are refused if the number of unauthenticated connections reaches
|
are refused if the number of unauthenticated connections reaches
|
||||||
.Dq full
|
.Dq full
|
||||||
(60).
|
(60).
|
||||||
@ -518,32 +622,40 @@ are refused if the number of unauthenticated connections reaches
|
|||||||
Specifies whether password authentication is allowed.
|
Specifies whether password authentication is allowed.
|
||||||
The default is
|
The default is
|
||||||
.Dq yes .
|
.Dq yes .
|
||||||
Note that this option applies to both protocol versions 1 and 2.
|
|
||||||
.It Cm PermitEmptyPasswords
|
.It Cm PermitEmptyPasswords
|
||||||
When password authentication is allowed, it specifies whether the
|
When password authentication is allowed, it specifies whether the
|
||||||
server allows login to accounts with empty password strings.
|
server allows login to accounts with empty password strings.
|
||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
.It Cm PermitRootLogin
|
.It Cm PermitRootLogin
|
||||||
Specifies whether the root can log in using
|
Specifies whether root can login using
|
||||||
.Xr ssh 1 .
|
.Xr ssh 1 .
|
||||||
The argument must be
|
The argument must be
|
||||||
.Dq yes ,
|
.Dq yes ,
|
||||||
.Dq without-password
|
.Dq without-password ,
|
||||||
|
.Dq forced-commands-only
|
||||||
or
|
or
|
||||||
.Dq no .
|
.Dq no .
|
||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
If this options is set to
|
|
||||||
.Dq without-password
|
|
||||||
only password authentication is disabled for root.
|
|
||||||
.Pp
|
.Pp
|
||||||
Root login with RSA authentication when the
|
If this option is set to
|
||||||
|
.Dq without-password
|
||||||
|
password authentication is disabled for root.
|
||||||
|
.Pp
|
||||||
|
If this option is set to
|
||||||
|
.Dq forced-commands-only
|
||||||
|
root login with public key authentication will be allowed,
|
||||||
|
but only if the
|
||||||
.Ar command
|
.Ar command
|
||||||
option has been
|
option has been specified
|
||||||
specified will be allowed regardless of the value of this setting
|
|
||||||
(which may be useful for taking remote backups even if root login is
|
(which may be useful for taking remote backups even if root login is
|
||||||
normally not allowed).
|
normally not allowed). All other authentication methods are disabled
|
||||||
|
for root.
|
||||||
|
.Pp
|
||||||
|
If this option is set to
|
||||||
|
.Dq no
|
||||||
|
root is not allowed to login.
|
||||||
.It Cm PidFile
|
.It Cm PidFile
|
||||||
Specifies the file that contains the process identifier of the
|
Specifies the file that contains the process identifier of the
|
||||||
.Nm
|
.Nm
|
||||||
@ -556,6 +668,14 @@ Specifies the port number that
|
|||||||
listens on.
|
listens on.
|
||||||
The default is 22.
|
The default is 22.
|
||||||
Multiple options of this type are permitted.
|
Multiple options of this type are permitted.
|
||||||
|
See also
|
||||||
|
.Cm ListenAddress .
|
||||||
|
.It Cm PrintLastLog
|
||||||
|
Specifies whether
|
||||||
|
.Nm
|
||||||
|
should print the date and time when the user last logged in.
|
||||||
|
The default is
|
||||||
|
.Dq yes .
|
||||||
.It Cm PrintMotd
|
.It Cm PrintMotd
|
||||||
Specifies whether
|
Specifies whether
|
||||||
.Nm
|
.Nm
|
||||||
@ -577,10 +697,20 @@ and
|
|||||||
.Dq 2 .
|
.Dq 2 .
|
||||||
Multiple versions must be comma-separated.
|
Multiple versions must be comma-separated.
|
||||||
The default is
|
The default is
|
||||||
.Dq 1 .
|
.Dq 2,1 .
|
||||||
.It Cm RandomSeed
|
.It Cm PubkeyAuthentication
|
||||||
Obsolete - accepted and ignored with a warning.
|
Specifies whether public key authentication is allowed.
|
||||||
Random number generation uses other techniques.
|
The default is
|
||||||
|
.Dq yes .
|
||||||
|
Note that this option applies to protocol version 2 only.
|
||||||
|
.It Cm ReverseMappingCheck
|
||||||
|
Specifies whether
|
||||||
|
.Nm
|
||||||
|
should try to verify the remote host name and check that
|
||||||
|
the resolved host name for the remote IP address maps back to the
|
||||||
|
very same IP address.
|
||||||
|
The default is
|
||||||
|
.Dq no .
|
||||||
.It Cm RhostsAuthentication
|
.It Cm RhostsAuthentication
|
||||||
Specifies whether authentication using rhosts or
|
Specifies whether authentication using rhosts or
|
||||||
.Pa /etc/hosts.equiv
|
.Pa /etc/hosts.equiv
|
||||||
@ -594,6 +724,7 @@ to normal rhosts or
|
|||||||
authentication.
|
authentication.
|
||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
This option applies to protocol version 1 only.
|
||||||
.It Cm RhostsRSAAuthentication
|
.It Cm RhostsRSAAuthentication
|
||||||
Specifies whether rhosts or
|
Specifies whether rhosts or
|
||||||
.Pa /etc/hosts.equiv
|
.Pa /etc/hosts.equiv
|
||||||
@ -601,13 +732,14 @@ authentication together
|
|||||||
with successful RSA host authentication is allowed.
|
with successful RSA host authentication is allowed.
|
||||||
The default is
|
The default is
|
||||||
.Dq no .
|
.Dq no .
|
||||||
|
This option applies to protocol version 1 only.
|
||||||
.It Cm RSAAuthentication
|
.It Cm RSAAuthentication
|
||||||
Specifies whether pure RSA authentication is allowed.
|
Specifies whether pure RSA authentication is allowed.
|
||||||
The default is
|
The default is
|
||||||
.Dq yes .
|
.Dq yes .
|
||||||
Note that this option applies to protocol version 1 only.
|
This option applies to protocol version 1 only.
|
||||||
.It Cm ServerKeyBits
|
.It Cm ServerKeyBits
|
||||||
Defines the number of bits in the server key.
|
Defines the number of bits in the ephemeral protocol version 1 server key.
|
||||||
The minimum value is 512, and the default is 768.
|
The minimum value is 512, and the default is 768.
|
||||||
.It Cm SkeyAuthentication
|
.It Cm SkeyAuthentication
|
||||||
Specifies whether
|
Specifies whether
|
||||||
@ -725,29 +857,41 @@ Runs user's shell or command.
|
|||||||
The
|
The
|
||||||
.Pa $HOME/.ssh/authorized_keys
|
.Pa $HOME/.ssh/authorized_keys
|
||||||
file lists the RSA keys that are
|
file lists the RSA keys that are
|
||||||
permitted for RSA authentication in SSH protocols 1.3 and 1.5
|
permitted for RSA authentication in protocol version 1
|
||||||
Similarly, the
|
Similarly, the
|
||||||
.Pa $HOME/.ssh/authorized_keys2
|
.Pa $HOME/.ssh/authorized_keys2
|
||||||
file lists the DSA keys that are
|
file lists the DSA and RSA keys that are
|
||||||
permitted for DSA authentication in SSH protocol 2.0.
|
permitted for public key authentication (PubkeyAuthentication)
|
||||||
|
in protocol version 2.
|
||||||
|
.Pp
|
||||||
Each line of the file contains one
|
Each line of the file contains one
|
||||||
key (empty lines and lines starting with a
|
key (empty lines and lines starting with a
|
||||||
.Ql #
|
.Ql #
|
||||||
are ignored as
|
are ignored as
|
||||||
comments).
|
comments).
|
||||||
Each line consists of the following fields, separated by
|
Each RSA public key consists of the following fields, separated by
|
||||||
spaces: options, bits, exponent, modulus, comment.
|
spaces: options, bits, exponent, modulus, comment.
|
||||||
The options field
|
Each protocol version 2 public key consists of:
|
||||||
is optional; its presence is determined by whether the line starts
|
options, keytype, base64 encoded key, comment.
|
||||||
|
The options fields
|
||||||
|
are optional; its presence is determined by whether the line starts
|
||||||
with a number or not (the option field never starts with a number).
|
with a number or not (the option field never starts with a number).
|
||||||
The bits, exponent, modulus and comment fields give the RSA key; the
|
The bits, exponent, modulus and comment fields give the RSA key for
|
||||||
|
protocol version 1; the
|
||||||
comment field is not used for anything (but may be convenient for the
|
comment field is not used for anything (but may be convenient for the
|
||||||
user to identify the key).
|
user to identify the key).
|
||||||
|
For protocol version 2 the keytype is
|
||||||
|
.Dq ssh-dss
|
||||||
|
or
|
||||||
|
.Dq ssh-rsa .
|
||||||
.Pp
|
.Pp
|
||||||
Note that lines in this file are usually several hundred bytes long
|
Note that lines in this file are usually several hundred bytes long
|
||||||
(because of the size of the RSA key modulus).
|
(because of the size of the RSA key modulus).
|
||||||
You don't want to type them in; instead, copy the
|
You don't want to type them in; instead, copy the
|
||||||
.Pa identity.pub
|
.Pa identity.pub ,
|
||||||
|
.Pa id_dsa.pub
|
||||||
|
or the
|
||||||
|
.Pa id_rsa.pub
|
||||||
file and edit it.
|
file and edit it.
|
||||||
.Pp
|
.Pp
|
||||||
The options (if present) consist of comma-separated option
|
The options (if present) consist of comma-separated option
|
||||||
@ -781,6 +925,9 @@ authentication.
|
|||||||
The command supplied by the user (if any) is ignored.
|
The command supplied by the user (if any) is ignored.
|
||||||
The command is run on a pty if the connection requests a pty;
|
The command is run on a pty if the connection requests a pty;
|
||||||
otherwise it is run without a tty.
|
otherwise it is run without a tty.
|
||||||
|
Note that if you want a 8-bit clean channel,
|
||||||
|
you must not request a pty or should specify
|
||||||
|
.Cm no-pty .
|
||||||
A quote may be included in the command by quoting it with a backslash.
|
A quote may be included in the command by quoting it with a backslash.
|
||||||
This option might be useful
|
This option might be useful
|
||||||
to restrict certain RSA keys to perform just a specific operation.
|
to restrict certain RSA keys to perform just a specific operation.
|
||||||
@ -807,13 +954,24 @@ Forbids authentication agent forwarding when this key is used for
|
|||||||
authentication.
|
authentication.
|
||||||
.It Cm no-pty
|
.It Cm no-pty
|
||||||
Prevents tty allocation (a request to allocate a pty will fail).
|
Prevents tty allocation (a request to allocate a pty will fail).
|
||||||
|
.It Cm permitopen="host:port"
|
||||||
|
Limit local
|
||||||
|
.Li ``ssh -L''
|
||||||
|
port forwarding such that it may only connect to the specified host and
|
||||||
|
port. Multiple
|
||||||
|
.Cm permitopen
|
||||||
|
options may be applied separated by commas. No pattern matching is
|
||||||
|
performed on the specified hostnames, they must be literal domains or
|
||||||
|
addresses.
|
||||||
.El
|
.El
|
||||||
.Ss Examples
|
.Ss Examples
|
||||||
.Bd -literal
|
1024 33 12121.\|.\|.\|312314325 ylo@foo.bar
|
||||||
1024 33 12121...312314325 ylo@foo.bar
|
.Pp
|
||||||
from="*.niksula.hut.fi,!pc.niksula.hut.fi" 1024 35 23...2334 ylo@niksula
|
from="*.niksula.hut.fi,!pc.niksula.hut.fi" 1024 35 23.\|.\|.\|2334 ylo@niksula
|
||||||
command="dump /home",no-pty,no-port-forwarding 1024 33 23...2323 backup.hut.fi
|
.Pp
|
||||||
.Ed
|
command="dump /home",no-pty,no-port-forwarding 1024 33 23.\|.\|.\|2323 backup.hut.fi
|
||||||
|
.Pp
|
||||||
|
permitopen="10.2.1.55:80",permitopen="10.2.1.56:25" 1024 33 23.\|.\|.\|2323
|
||||||
.Sh SSH_KNOWN_HOSTS FILE FORMAT
|
.Sh SSH_KNOWN_HOSTS FILE FORMAT
|
||||||
The
|
The
|
||||||
.Pa /etc/ssh/ssh_known_hosts ,
|
.Pa /etc/ssh/ssh_known_hosts ,
|
||||||
@ -869,7 +1027,8 @@ or by taking
|
|||||||
and adding the host names at the front.
|
and adding the host names at the front.
|
||||||
.Ss Examples
|
.Ss Examples
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
closenet,closenet.hut.fi,...,130.233.208.41 1024 37 159...93 closenet.hut.fi
|
closenet,.\|.\|.\|,130.233.208.41 1024 37 159.\|.\|.93 closenet.hut.fi
|
||||||
|
cvs.openbsd.org,199.185.137.3 ssh-rsa AAAA1234.....=
|
||||||
.Ed
|
.Ed
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
@ -878,23 +1037,25 @@ Contains configuration data for
|
|||||||
.Nm sshd .
|
.Nm sshd .
|
||||||
This file should be writable by root only, but it is recommended
|
This file should be writable by root only, but it is recommended
|
||||||
(though not necessary) that it be world-readable.
|
(though not necessary) that it be world-readable.
|
||||||
.It Pa /etc/ssh/ssh_host_key
|
.It Pa /etc/ssh/ssh_host_key, /etc/ssh/ssh_host_dsa_key, /etc/ssh/ssh_host_rsa_key
|
||||||
Contains the private part of the host key.
|
These three files contain the private parts of the host keys.
|
||||||
This file should only be owned by root, readable only by root, and not
|
These files should only be owned by root, readable only by root, and not
|
||||||
accessible to others.
|
accessible to others.
|
||||||
Note that
|
Note that
|
||||||
.Nm
|
.Nm
|
||||||
does not start if this file is group/world-accessible.
|
does not start if this file is group/world-accessible.
|
||||||
.It Pa /etc/ssh/ssh_host_key.pub
|
.It Pa /etc/ssh/ssh_host_key.pub, /etc/ssh/ssh_host_dsa_key.pub, /etc/ssh/ssh_host_rsa_key.pub
|
||||||
Contains the public part of the host key.
|
These three files contain the public parts of the host keys.
|
||||||
This file should be world-readable but writable only by
|
These files should be world-readable but writable only by
|
||||||
root.
|
root.
|
||||||
Its contents should match the private part.
|
Their contents should match the respective private parts.
|
||||||
This file is not
|
These files are not
|
||||||
really used for anything; it is only provided for the convenience of
|
really used for anything; they are provided for the convenience of
|
||||||
the user so its contents can be copied to known hosts files.
|
the user so their contents can be copied to known hosts files.
|
||||||
These two files are created using
|
These files are created using
|
||||||
.Xr ssh-keygen 1 .
|
.Xr ssh-keygen 1 .
|
||||||
|
.It Pa /etc/primes
|
||||||
|
Contains Diffie-Hellman groups used for the "Diffie-Hellman Group Exchange".
|
||||||
.It Pa /var/run/sshd.pid
|
.It Pa /var/run/sshd.pid
|
||||||
Contains the process ID of the
|
Contains the process ID of the
|
||||||
.Nm
|
.Nm
|
||||||
@ -914,7 +1075,7 @@ Users will place the contents of their
|
|||||||
files into this file, as described in
|
files into this file, as described in
|
||||||
.Xr ssh-keygen 1 .
|
.Xr ssh-keygen 1 .
|
||||||
.It Pa $HOME/.ssh/authorized_keys2
|
.It Pa $HOME/.ssh/authorized_keys2
|
||||||
Lists the DSA keys that can be used to log into the user's account.
|
Lists the public keys (RSA or DSA) that can be used to log into the user's account.
|
||||||
This file must be readable by root (which may on some machines imply
|
This file must be readable by root (which may on some machines imply
|
||||||
it being world-readable if the user's home directory resides on an NFS
|
it being world-readable if the user's home directory resides on an NFS
|
||||||
volume).
|
volume).
|
||||||
@ -922,6 +1083,8 @@ It is recommended that it not be accessible by others.
|
|||||||
The format of this file is described above.
|
The format of this file is described above.
|
||||||
Users will place the contents of their
|
Users will place the contents of their
|
||||||
.Pa id_dsa.pub
|
.Pa id_dsa.pub
|
||||||
|
and/or
|
||||||
|
.Pa id_rsa.pub
|
||||||
files into this file, as described in
|
files into this file, as described in
|
||||||
.Xr ssh-keygen 1 .
|
.Xr ssh-keygen 1 .
|
||||||
.It Pa "/etc/ssh/ssh_known_hosts" and "$HOME/.ssh/known_hosts"
|
.It Pa "/etc/ssh/ssh_known_hosts" and "$HOME/.ssh/known_hosts"
|
||||||
@ -929,12 +1092,23 @@ These files are consulted when using rhosts with RSA host
|
|||||||
authentication to check the public key of the host.
|
authentication to check the public key of the host.
|
||||||
The key must be listed in one of these files to be accepted.
|
The key must be listed in one of these files to be accepted.
|
||||||
The client uses the same files
|
The client uses the same files
|
||||||
to verify that the remote host is the one it intended to connect.
|
to verify that it is connecting to the correct remote host.
|
||||||
These files should be writable only by root/the owner.
|
These files should be writable only by root/the owner.
|
||||||
.Pa /etc/ssh/ssh_known_hosts
|
.Pa /etc/ssh/ssh_known_hosts
|
||||||
should be world-readable, and
|
should be world-readable, and
|
||||||
.Pa $HOME/.ssh/known_hosts
|
.Pa $HOME/.ssh/known_hosts
|
||||||
can but need not be world-readable.
|
can but need not be world-readable.
|
||||||
|
.It Pa "/etc/ssh_known_hosts2" and "$HOME/.ssh/known_hosts2"
|
||||||
|
These files are consulted when using protocol version 2 hostbased
|
||||||
|
authentication to check the public key of the host.
|
||||||
|
The key must be listed in one of these files to be accepted.
|
||||||
|
The client uses the same files
|
||||||
|
to verify that it is connecting to the correct remote host.
|
||||||
|
These files should be writable only by root/the owner.
|
||||||
|
.Pa /etc/ssh_known_hosts2
|
||||||
|
should be world-readable, and
|
||||||
|
.Pa $HOME/.ssh/known_hosts2
|
||||||
|
can but need not be world-readable.
|
||||||
.It Pa /etc/nologin
|
.It Pa /etc/nologin
|
||||||
If this file exists,
|
If this file exists,
|
||||||
.Nm
|
.Nm
|
||||||
@ -1037,7 +1211,7 @@ This file will probably contain some initialization code followed by
|
|||||||
something similar to:
|
something similar to:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
if [ -n "$DISPLAY" ] && read proto cookie; then
|
if [ -n "$DISPLAY" ] && read proto cookie; then
|
||||||
echo add $DISPLAY $proto $cookie | xauth -q -
|
echo add "$DISPLAY" "$proto" "$cookie" | xauth -q -
|
||||||
fi
|
fi
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
@ -1057,45 +1231,42 @@ This can be used to specify
|
|||||||
machine-specific login-time initializations globally.
|
machine-specific login-time initializations globally.
|
||||||
This file should be writable only by root, and should be world-readable.
|
This file should be writable only by root, and should be world-readable.
|
||||||
.El
|
.El
|
||||||
.Sh AUTHOR
|
.Sh AUTHORS
|
||||||
OpenSSH
|
OpenSSH is a derivative of the original and free
|
||||||
is a derivative of the original (free) ssh 1.2.12 release by Tatu Ylonen,
|
ssh 1.2.12 release by Tatu Ylonen.
|
||||||
but with bugs removed and newer features re-added.
|
Aaron Campbell, Bob Beck, Markus Friedl, Niels Provos,
|
||||||
Rapidly after the
|
Theo de Raadt and Dug Song
|
||||||
1.2.12 release, newer versions of the original ssh bore successively
|
removed many bugs, re-added newer features and
|
||||||
more restrictive licenses, and thus demand for a free version was born.
|
created OpenSSH.
|
||||||
.Pp
|
Markus Friedl contributed the support for SSH
|
||||||
This version of OpenSSH
|
protocol versions 1.5 and 2.0.
|
||||||
.Bl -bullet
|
|
||||||
.It
|
|
||||||
has all components of a restrictive nature (i.e., patents, see
|
|
||||||
.Xr ssl 8 )
|
|
||||||
directly removed from the source code; any licensed or patented components
|
|
||||||
are chosen from
|
|
||||||
external libraries.
|
|
||||||
.It
|
|
||||||
has been updated to support SSH protocol 1.5 and 2, making it compatible with
|
|
||||||
all other SSH clients and servers.
|
|
||||||
.It
|
|
||||||
contains added support for
|
|
||||||
.Xr kerberos 8
|
|
||||||
authentication and ticket passing.
|
|
||||||
.It
|
|
||||||
supports one-time password authentication with
|
|
||||||
.Xr skey 1 .
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
OpenSSH has been created by Aaron Campbell, Bob Beck, Markus Friedl,
|
|
||||||
Niels Provos, Theo de Raadt, and Dug Song.
|
|
||||||
.Pp
|
|
||||||
The support for SSH protocol 2 was written by Markus Friedl.
|
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr scp 1 ,
|
.Xr scp 1 ,
|
||||||
|
.Xr sftp 1 ,
|
||||||
.Xr sftp-server 8 ,
|
.Xr sftp-server 8 ,
|
||||||
.Xr ssh 1 ,
|
.Xr ssh 1 ,
|
||||||
.Xr ssh-add 1 ,
|
.Xr ssh-add 1 ,
|
||||||
.Xr ssh-agent 1 ,
|
.Xr ssh-agent 1 ,
|
||||||
.Xr ssh-keygen 1 ,
|
.Xr ssh-keygen 1 ,
|
||||||
.Xr ssl 8 ,
|
|
||||||
.Xr rlogin 1 ,
|
.Xr rlogin 1 ,
|
||||||
.Xr rsh 1
|
.Xr rsh 1
|
||||||
|
.Rs
|
||||||
|
.%A T. Ylonen
|
||||||
|
.%A T. Kivinen
|
||||||
|
.%A M. Saarinen
|
||||||
|
.%A T. Rinne
|
||||||
|
.%A S. Lehtinen
|
||||||
|
.%T "SSH Protocol Architecture"
|
||||||
|
.%N draft-ietf-secsh-architecture-07.txt
|
||||||
|
.%D January 2001
|
||||||
|
.%O work in progress material
|
||||||
|
.Re
|
||||||
|
.Rs
|
||||||
|
.%A M. Friedl
|
||||||
|
.%A N. Provos
|
||||||
|
.%A W. A. Simpson
|
||||||
|
.%T "Diffie-Hellman Group Exchange for the SSH Transport Layer Protocol"
|
||||||
|
.%N draft-ietf-secsh-dh-group-exchange-00.txt
|
||||||
|
.%D January 2001
|
||||||
|
.%O work in progress material
|
||||||
|
.Re
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,16 @@
|
|||||||
# This is ssh server systemwide configuration file.
|
# $OpenBSD: sshd_config,v 1.38 2001/04/15 21:41:29 deraadt Exp $
|
||||||
#
|
# $FreeBSD$
|
||||||
# $FreeBSD$
|
|
||||||
|
# This is the sshd server system-wide configuration file. See sshd(8)
|
||||||
|
# for more information.
|
||||||
|
|
||||||
Port 22
|
Port 22
|
||||||
#Protocol 2,1
|
#Protocol 2,1
|
||||||
#ListenAddress 0.0.0.0
|
#ListenAddress 0.0.0.0
|
||||||
#ListenAddress ::
|
#ListenAddress ::
|
||||||
HostKey /etc/ssh/ssh_host_key
|
HostKey /etc/ssh_host_key
|
||||||
HostDsaKey /etc/ssh/ssh_host_dsa_key
|
HostKey /etc/ssh_host_rsa_key
|
||||||
|
HostKey /etc/ssh_host_dsa_key
|
||||||
ServerKeyBits 768
|
ServerKeyBits 768
|
||||||
LoginGraceTime 120
|
LoginGraceTime 120
|
||||||
KeyRegenerationInterval 3600
|
KeyRegenerationInterval 3600
|
||||||
@ -25,6 +28,7 @@ StrictModes yes
|
|||||||
X11Forwarding yes
|
X11Forwarding yes
|
||||||
X11DisplayOffset 10
|
X11DisplayOffset 10
|
||||||
PrintMotd yes
|
PrintMotd yes
|
||||||
|
#PrintLastLog no
|
||||||
KeepAlive yes
|
KeepAlive yes
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
@ -36,15 +40,17 @@ RhostsAuthentication no
|
|||||||
#
|
#
|
||||||
# For this to work you will also need host keys in /etc/ssh_known_hosts
|
# For this to work you will also need host keys in /etc/ssh_known_hosts
|
||||||
RhostsRSAAuthentication no
|
RhostsRSAAuthentication no
|
||||||
|
# similar for protocol version 2
|
||||||
|
HostbasedAuthentication no
|
||||||
#
|
#
|
||||||
RSAAuthentication yes
|
RSAAuthentication yes
|
||||||
|
|
||||||
# To disable tunneled clear text passwords, change to no here!
|
# To disable tunneled clear text passwords, change to no here!
|
||||||
PasswordAuthentication yes
|
PasswordAuthentication yes
|
||||||
PermitEmptyPasswords no
|
PermitEmptyPasswords no
|
||||||
|
|
||||||
# Uncomment to disable s/key passwords
|
# Uncomment to disable s/key passwords
|
||||||
#SkeyAuthentication no
|
#ChallengeResponseAuthentication no
|
||||||
#KbdInteractiveAuthentication yes
|
|
||||||
|
|
||||||
# To change Kerberos options
|
# To change Kerberos options
|
||||||
#KerberosAuthentication no
|
#KerberosAuthentication no
|
||||||
@ -58,5 +64,8 @@ PermitEmptyPasswords no
|
|||||||
CheckMail yes
|
CheckMail yes
|
||||||
#UseLogin no
|
#UseLogin no
|
||||||
|
|
||||||
# Uncomment if you want to enable sftp
|
#MaxStartups 10:30:60
|
||||||
#Subsystem sftp /usr/libexec/sftp-server
|
#Banner /etc/issue.net
|
||||||
|
#ReverseMappingCheck yes
|
||||||
|
|
||||||
|
Subsystem sftp /usr/libexec/sftp-server
|
||||||
|
@ -40,8 +40,9 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: sshlogin.c,v 1.2 2001/03/24 16:43:27 stevesk Exp $");
|
RCSID("$OpenBSD: sshlogin.c,v 1.2 2001/03/24 16:43:27 stevesk Exp $");
|
||||||
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include <util.h>
|
#include <libutil.h>
|
||||||
#include <utmp.h>
|
#include <utmp.h>
|
||||||
#include "sshlogin.h"
|
#include "sshlogin.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
@ -13,8 +13,9 @@
|
|||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
RCSID("$OpenBSD: sshpty.c,v 1.1 2001/03/04 01:46:30 djm Exp $");
|
RCSID("$OpenBSD: sshpty.c,v 1.1 2001/03/04 01:46:30 djm Exp $");
|
||||||
|
RCSID("$FreeBSD$");
|
||||||
|
|
||||||
#include <util.h>
|
#include <libutil.h>
|
||||||
#include "sshpty.h"
|
#include "sshpty.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
/* $FreeBSD$ */
|
/* $FreeBSD$ */
|
||||||
/* $OpenBSD: version.h,v 1.13 2000/10/16 09:38:45 djm Exp $ */
|
/* $OpenBSD: version.h,v 1.23 2001/04/24 16:43:16 markus Exp $ */
|
||||||
|
|
||||||
#ifndef SSH_VERSION
|
#ifndef SSH_VERSION
|
||||||
|
|
||||||
#define SSH_VERSION (ssh_version_get())
|
#define SSH_VERSION (ssh_version_get())
|
||||||
#define SSH_VERSION_BASE "OpenSSH_2.3.0"
|
#define SSH_VERSION_BASE "OpenSSH_2.9"
|
||||||
#define SSH_VERSION_ADDENDUM "green@FreeBSD.org 20010319"
|
#define SSH_VERSION_ADDENDUM "green@FreeBSD.org 20010503"
|
||||||
|
|
||||||
const char *ssh_version_get(void);
|
const char *ssh_version_get(void);
|
||||||
void ssh_version_set_addendum(const char *add);
|
void ssh_version_set_addendum(const char *add);
|
||||||
|
Loading…
Reference in New Issue
Block a user