Resolve conflicts and update for FreeBSD.

This commit is contained in:
Kris Kennaway 2000-05-15 05:24:25 +00:00
parent fe01acb846
commit e8aafc91b5
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=60576
39 changed files with 2833 additions and 4227 deletions

View File

@ -1,10 +1,11 @@
$FreeBSD$
$Id: README.openssh2,v 1.8 2000/05/07 18:30:03 markus Exp $
howto:
1) generate server key:
$ ssh-keygen -d -f /etc/ssh_host_dsa_key -N ''
$ ssh-keygen -d -f /etc/ssh/ssh_host_dsa_key -N ''
2) enable ssh2:
server: add 'Protocol 2,1' to /etc/sshd_config
server: add 'Protocol 2,1' to /etc/ssh/sshd_config
client: ssh -o 'Protocol 2,1', or add to .ssh/config
3) DSA authentication similar to RSA (add keys to ~/.ssh/authorized_keys2)
interop w/ ssh.com dsa-keys:

View File

@ -21,7 +21,7 @@ extern ServerOptions options;
* return 1 on success, 0 on failure, -1 if krb4 is not available
*/
int
int
auth_krb4_password(struct passwd * pw, const char *password)
{
AUTH_DAT adata;
@ -137,7 +137,7 @@ krb4_cleanup_proc(void *ignore)
}
}
int
int
krb4_init(uid_t uid)
{
static int cleanup_registered = 0;
@ -181,7 +181,7 @@ krb4_init(uid_t uid)
return 0;
}
int
int
auth_krb4(const char *server_user, KTEXT auth, char **client)
{
AUTH_DAT adat = {0};
@ -254,7 +254,7 @@ auth_krb4(const char *server_user, KTEXT auth, char **client)
#endif /* KRB4 */
#ifdef AFS
int
int
auth_krb4_tgt(struct passwd *pw, const char *string)
{
CREDENTIALS creds;
@ -309,7 +309,7 @@ auth_krb4_tgt(struct passwd *pw, const char *string)
return 0;
}
int
int
auth_afs_token(struct passwd *pw, const char *token_string)
{
CREDENTIALS creds;

View File

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$Id: auth-passwd.c,v 1.14 1999/12/29 12:47:46 markus Exp $");
RCSID("$Id: auth-passwd.c,v 1.15 2000/04/14 10:30:29 markus Exp $");
#include "packet.h"
#include "ssh.h"

View File

@ -1,14 +1,14 @@
/*
*
*
* auth-rh-rsa.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Sun May 7 03:08:06 1995 ylo
*
*
* Rhosts or /etc/hosts.equiv authentication combined with RSA host
* authentication.
*
@ -16,7 +16,7 @@
*/
#include "includes.h"
RCSID("$Id: auth-rh-rsa.c,v 1.11 2000/03/23 22:15:33 markus Exp $");
RCSID("$Id: auth-rh-rsa.c,v 1.13 2000/04/14 10:30:29 markus Exp $");
#include "packet.h"
#include "ssh.h"
@ -34,7 +34,7 @@ RCSID("$Id: auth-rh-rsa.c,v 1.11 2000/03/23 22:15:33 markus Exp $");
* its host key. Returns true if authentication succeeds.
*/
int
int
auth_rhosts_rsa(struct passwd *pw, const char *client_user, RSA *client_host_key)
{
extern ServerOptions options;

View File

@ -1,23 +1,23 @@
/*
*
*
* auth-rsa.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Mon Mar 27 01:46:52 1995 ylo
*
*
* RSA-based authentication. This code determines whether to admit a login
* based on RSA authentication. This file also contains functions to check
* validity of the host key.
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: auth-rsa.c,v 1.19 2000/03/23 22:15:33 markus Exp $");
RCSID("$Id: auth-rsa.c,v 1.23 2000/04/29 18:11:51 markus Exp $");
#include "rsa.h"
#include "packet.h"
@ -186,6 +186,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
}
}
if (fail) {
fclose(f);
log(buf);
packet_send_debug(buf);
restore_uid();
@ -239,7 +240,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
debug("%.100s, line %lu: bad key syntax",
SSH_USER_PERMITTED_KEYS, linenum);
packet_send_debug("%.100s, line %lu: bad key syntax",
SSH_USER_PERMITTED_KEYS, linenum);
SSH_USER_PERMITTED_KEYS, linenum);
continue;
}
/* cp now points to the comment part. */
@ -256,7 +257,6 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
/* We have found the desired key. */
/* Perform the challenge-response dialog for this key. */
if (!auth_rsa_challenge_dialog(pk)) {
/* Wrong response. */

View File

@ -1,9 +1,12 @@
/* $FreeBSD$ */
#include "includes.h"
RCSID("$Id: auth-skey.c,v 1.6 2000/04/14 10:30:29 markus Exp $");
#include <sys/sysctl.h>
#include "ssh.h"
#include "packet.h"
#include <sha1.h>
#include <sha.h>
/*
* try skey authentication,
@ -14,7 +17,7 @@ int
auth_skey_password(struct passwd * pw, const char *password)
{
if (strncasecmp(password, "s/key", 5) == 0) {
char *skeyinfo = skey_keyinfo(pw->pw_name);
char *skeyinfo = opie_keyinfo(pw->pw_name);
if (skeyinfo == NULL) {
debug("generating fake skeyinfo for %.100s.",
pw->pw_name);
@ -24,8 +27,8 @@ auth_skey_password(struct passwd * pw, const char *password)
packet_send_debug(skeyinfo);
/* Try again. */
return 0;
} else if (skey_haskey(pw->pw_name) == 0 &&
skey_passcheck(pw->pw_name, (char *) password) != -1) {
} else if (opie_haskey(pw->pw_name) == 0 &&
opie_passverify(pw->pw_name, (char *) password) != -1) {
/* Authentication succeeded. */
return 1;
}
@ -64,16 +67,19 @@ skey_fake_keyinfo(char *username)
{
int i;
u_int ptr;
u_char hseed[SKEY_MAX_SEED_LEN], flg = 1, *up;
char pbuf[SKEY_MAX_PW_LEN+1];
static char skeyprompt[SKEY_MAX_CHALLENGE+1];
u_char hseed[OPIE_SEED_MAX], flg = 1, *up;
char pbuf[OPIE_SECRET_MAX+1];
static char skeyprompt[OPIE_CHALLENGE_MAX+1];
char *secret = NULL;
size_t secretlen = 0;
SHA1_CTX ctx;
char *p, *u;
int mib[2];
size_t size;
struct timeval boottime;
/*
* Base first 4 chars of seed on hostname.
* Base first 2 chars of seed on hostname.
* Add some filler for short hostnames if necessary.
*/
if (gethostname(pbuf, sizeof(pbuf)) == -1)
@ -82,31 +88,34 @@ skey_fake_keyinfo(char *username)
for (p = pbuf; *p && isalnum(*p); p++)
if (isalpha(*p) && isupper(*p))
*p = tolower(*p);
if (*p && pbuf - p < 4)
(void)strncpy(p, "asjd", 4 - (pbuf - p));
pbuf[4] = '\0';
if (*p && pbuf - p < 2)
(void)strncpy(p, "asjd", 2 - (pbuf - p));
pbuf[2] = '\0';
/* Hash the username if possible */
if ((up = SHA1Data(username, strlen(username), NULL)) != NULL) {
if ((up = SHA1_Data(username, strlen(username), NULL)) != NULL) {
struct stat sb;
time_t t;
int fd;
/* Collapse the hash */
ptr = hash_collapse(up);
memset(up, 0, strlen(up));
/* See if the random file's there, else use ctime */
if ((fd = open(_SKEY_RAND_FILE_PATH_, O_RDONLY)) != -1
&& fstat(fd, &sb) == 0 &&
sb.st_size > (off_t)SKEY_MAX_SEED_LEN &&
lseek(fd, ptr % (sb.st_size - SKEY_MAX_SEED_LEN),
SEEK_SET) != -1 && read(fd, hseed,
SKEY_MAX_SEED_LEN) == SKEY_MAX_SEED_LEN) {
close(fd);
fd = -1;
secret = hseed;
secretlen = SKEY_MAX_SEED_LEN;
/*
* Seed the fake challenge with the system boot time,
* otherwise use ctime.
*
* XXX This should be a random source which is constant
* over short time periods, but changes over timescales on
* the order of a week.
*/
mib[0] = CTL_KERN;
mib[1] = KERN_BOOTTIME;
size = sizeof(boottime);
if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
boottime.tv_sec != 0) {
secret = (char *)&boottime;
secretlen = size/sizeof(char);
flg = 0;
} else if (!stat(_PATH_MEM, &sb) || !stat("/", &sb)) {
t = sb.st_ctime;
@ -114,51 +123,49 @@ skey_fake_keyinfo(char *username)
secretlen = strlen(secret);
flg = 0;
}
if (fd != -1)
close(fd);
}
/* Put that in your pipe and smoke it */
if (flg == 0) {
/* Hash secret value with username */
SHA1Init(&ctx);
SHA1Update(&ctx, secret, secretlen);
SHA1Update(&ctx, username, strlen(username));
SHA1End(&ctx, up);
SHA1_Init(&ctx);
SHA1_Update(&ctx, secret, secretlen);
SHA1_Update(&ctx, username, strlen(username));
SHA1_End(&ctx, up);
/* Zero out */
memset(secret, 0, secretlen);
/* Now hash the hash */
SHA1Init(&ctx);
SHA1Update(&ctx, up, strlen(up));
SHA1End(&ctx, up);
SHA1_Init(&ctx);
SHA1_Update(&ctx, up, strlen(up));
SHA1_End(&ctx, up);
ptr = hash_collapse(up + 4);
for (i = 4; i < 9; i++) {
for (i = 2; i < 6; i++) {
pbuf[i] = (ptr % 10) + '0';
ptr /= 10;
}
pbuf[i] = '\0';
/* Sequence number */
ptr = ((up[2] + up[3]) % 99) + 1;
ptr = ((up[2] + up[3]) % 499) + 1;
memset(up, 0, 20); /* SHA1 specific */
free(up);
(void)snprintf(skeyprompt, sizeof skeyprompt,
"otp-%.*s %d %.*s",
SKEY_MAX_HASHNAME_LEN,
skey_get_algorithm(),
ptr, SKEY_MAX_SEED_LEN,
"opt-%.*s %d %.*s ext",
OPIE_HASHNAME_MAX,
opie_get_algorithm(),
ptr, OPIE_SEED_MAX,
pbuf);
} else {
/* Base last 8 chars of seed on username */
/* Base last 4 chars of seed on username */
u = username;
i = 8;
p = &pbuf[4];
i = 4;
p = &pbuf[2];
do {
if (*u == 0) {
/* Pad remainder with zeros */
@ -169,13 +176,11 @@ skey_fake_keyinfo(char *username)
*p++ = (*u++ % 10) + '0';
} while (--i != 0);
pbuf[12] = '\0';
pbuf[6] = '\0';
(void)snprintf(skeyprompt, sizeof skeyprompt,
"otp-%.*s %d %.*s",
SKEY_MAX_HASHNAME_LEN,
skey_get_algorithm(),
99, SKEY_MAX_SEED_LEN, pbuf);
"opt-md5 %d %.*s ext",
499, OPIE_SEED_MAX, pbuf);
}
return skeyprompt;
}

View File

@ -2,6 +2,8 @@
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* $FreeBSD$
*/
#include "includes.h"
@ -106,6 +108,16 @@ allowed_user(struct passwd * pw)
return 0;
}
}
#ifndef __FreeBSD__ /* FreeBSD handle it later */
/* Fail if the account's expiration time has passed. */
if (pw->pw_expire != 0) {
struct timeval tv;
(void)gettimeofday(&tv, NULL);
if (tv.tv_sec >= pw->pw_expire)
return 0;
}
#endif /* !__FreeBSD__ */
/* We found no reason not to let this user try to log on... */
return 1;
}

View File

@ -1,6 +1,8 @@
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
* $FreeBSD$
*/
#include "includes.h"
@ -39,9 +41,13 @@ get_authname(int type)
case SSH_CMSG_AUTH_RHOSTS:
return "rhosts";
#ifdef KRB4
case SSH_CMSG_AUTH_KERBEROS:
return "kerberos";
case SSH_CMSG_AUTH_KRB4:
return "kerberosV4";
#endif
#ifdef KRB5
case SSH_CMSG_AUTH_KRB5:
return "kerberosV5";
#endif /* KRB5 */
#ifdef SKEY
case SSH_CMSG_AUTH_TIS_RESPONSE:
return "s/key";
@ -135,6 +141,31 @@ do_authloop(struct passwd * pw)
unsigned int ulen;
int type = 0;
void (*authlog) (const char *fmt,...) = verbose;
#ifdef LOGIN_CAP
login_cap_t *lc;
#endif /* LOGIN_CAP */
#if defined(LOGIN_CAP) || defined(LOGIN_ACCESS)
const char *from_host, *from_ip;
from_host = get_canonical_hostname();
from_ip = get_remote_ipaddr();
#endif /* LOGIN_CAP || LOGIN_ACCESS */
#ifdef HAVE_LIBPAM
int pam_retval;
#endif /* HAVE_LIBPAM */
#if 0
#ifdef KRB5
{
krb5_error_code ret;
ret = krb5_init_context(&ssh_context);
if (ret)
verbose("Error while initializing Kerberos V5.");
krb5_init_ets(ssh_context);
}
#endif /* KRB5 */
#endif
/* Indicate that authentication is needed. */
packet_start(SSH_SMSG_FAILURE);
@ -151,17 +182,17 @@ do_authloop(struct passwd * pw)
/* Process the packet. */
switch (type) {
#ifdef AFS
case SSH_CMSG_HAVE_KERBEROS_TGT:
if (!options.kerberos_tgt_passing) {
case SSH_CMSG_HAVE_KRB4_TGT:
if (!options.krb4_tgt_passing) {
/* packet_get_all(); */
verbose("Kerberos tgt passing disabled.");
verbose("Kerberos v4 tgt passing disabled.");
break;
} else {
/* Accept Kerberos tgt. */
/* Accept Kerberos v4 tgt. */
char *tgt = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
if (!auth_kerberos_tgt(pw, tgt))
verbose("Kerberos tgt REFUSED for %s", pw->pw_name);
if (!auth_krb4_tgt(pw, tgt))
verbose("Kerberos v4 tgt REFUSED for %s", pw->pw_name);
xfree(tgt);
}
continue;
@ -182,11 +213,10 @@ do_authloop(struct passwd * pw)
continue;
#endif /* AFS */
#ifdef KRB4
case SSH_CMSG_AUTH_KERBEROS:
if (!options.kerberos_authentication) {
case SSH_CMSG_AUTH_KRB4:
if (!options.krb4_authentication) {
/* packet_get_all(); */
verbose("Kerberos authentication disabled.");
break;
verbose("Kerberos v4 authentication disabled.");
} else {
/* Try Kerberos v4 authentication. */
KTEXT_ST auth;
@ -207,6 +237,36 @@ do_authloop(struct passwd * pw)
}
break;
#endif /* KRB4 */
#ifdef KRB5
case SSH_CMSG_AUTH_KRB5:
if (!options.krb5_authentication) {
verbose("Kerberos v5 authentication disabled.");
break;
} else {
krb5_data k5data;
#if 0
if (krb5_init_context(&ssh_context)) {
verbose("Error while initializing Kerberos V5.");
break;
}
krb5_init_ets(ssh_context);
#endif
k5data.data = packet_get_string(&k5data.length);
packet_integrity_check(plen, 4 + k5data.length, type);
if (auth_krb5(pw->pw_name, &k5data, &tkt_client)) {
/* pw->name is passed just for logging purposes
* */
/* authorize client against .k5login */
if (krb5_kuserok(ssh_context,
tkt_client,
pw->pw_name))
authenticated = 1;
}
xfree(k5data.data);
}
break;
#endif /* KRB5 */
case SSH_CMSG_AUTH_RHOSTS:
if (!options.rhosts_authentication) {
@ -303,7 +363,7 @@ do_authloop(struct passwd * pw)
case SSH_CMSG_AUTH_TIS:
debug("rcvd SSH_CMSG_AUTH_TIS");
if (options.skey_authentication == 1) {
char *skeyinfo = skey_keyinfo(pw->pw_name);
char *skeyinfo = opie_keyinfo(pw->pw_name);
if (skeyinfo == NULL) {
debug("generating fake skeyinfo for %.100s.", pw->pw_name);
skeyinfo = skey_fake_keyinfo(pw->pw_name);
@ -325,8 +385,8 @@ do_authloop(struct passwd * pw)
char *response = packet_get_string(&dlen);
debug("skey response == '%s'", response);
packet_integrity_check(plen, 4 + dlen, type);
authenticated = (skey_haskey(pw->pw_name) == 0 &&
skey_passcheck(pw->pw_name, response) != -1);
authenticated = (opie_haskey(pw->pw_name) == 0 &&
opie_passverify(pw->pw_name, response) != -1);
xfree(response);
}
break;
@ -336,6 +396,32 @@ do_authloop(struct passwd * pw)
log("TIS authentication unsupported.");
break;
#endif
#ifdef KRB5
case SSH_CMSG_HAVE_KRB5_TGT:
/* Passing krb5 ticket */
if (!options.krb5_tgt_passing
/*|| !options.krb5_authentication */) {
}
if (tkt_client == NULL) {
/* passing tgt without krb5 authentication */
}
{
krb5_data tgt;
tgt.data = packet_get_string(&tgt.length);
if (!auth_krb5_tgt(pw->pw_name, &tgt, tkt_client)) {
verbose ("Kerberos V5 TGT refused for %.100s", pw->pw_name);
xfree(tgt.data);
goto fail;
}
xfree(tgt.data);
break;
}
#endif /* KRB5 */
default:
/*
@ -359,6 +445,34 @@ do_authloop(struct passwd * pw)
log("ROOT LOGIN REFUSED FROM %.200s",
get_canonical_hostname());
}
#ifdef LOGIN_CAP
lc = login_getpwclass(pw);
if (lc == NULL)
lc = login_getclassbyname(NULL, pw);
if (!auth_hostok(lc, from_host, from_ip)) {
log("Denied connection for %.200s from %.200s [%.200s].",
pw->pw_name, from_host, from_ip);
packet_disconnect("Sorry, you are not allowed to connect.");
}
if (!auth_timeok(lc, time(NULL))) {
log("LOGIN %.200s REFUSED (TIME) FROM %.200s",
pw->pw_name, from_host);
packet_disconnect("Logins not available right now.");
}
login_close(lc);
#endif /* LOGIN_CAP */
#ifdef LOGIN_ACCESS
if (!login_access(pw->pw_name, from_host)) {
log("Denied connection for %.200s from %.200s [%.200s].",
pw->pw_name, from_host, from_ip);
packet_disconnect("Sorry, you are not allowed to connect.");
}
#endif /* LOGIN_ACCESS */
if (pw->pw_uid == 0)
log("ROOT LOGIN as '%.100s' from %.100s",
pw->pw_name, get_canonical_hostname());
}
/* Raise logging level */
@ -431,6 +545,9 @@ do_authentication()
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;
/*
@ -444,8 +561,11 @@ do_authentication()
/* If the user has no password, accept authentication immediately. */
if (options.password_authentication &&
#ifdef KRB5
!options.krb5_authentication &&
#endif /* KRB5 */
#ifdef KRB4
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
(!options.krb4_authentication || options.krb4_or_local_passwd) &&
#endif /* KRB4 */
auth_password(pw, "")) {
/* Authentication with empty password succeeded. */

View File

@ -25,6 +25,8 @@
* 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.
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$OpenBSD: auth2.c,v 1.8 2000/05/08 17:42:24 markus Exp $");
@ -97,7 +99,7 @@ do_authentication2()
options.skey_authentication = 0;
#endif
#ifdef KRB4
options.kerberos_authentication = 0;
options.krb4_authentication = 0;
#endif
dispatch_init(&protocol_error);

View File

@ -1,21 +1,21 @@
/*
*
*
* authfd.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Wed Mar 29 01:30:28 1995 ylo
*
*
* Functions for connecting the local authentication agent.
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: authfd.c,v 1.16 1999/12/15 19:43:10 markus Exp $");
RCSID("$Id: authfd.c,v 1.19 2000/04/29 18:11:52 markus Exp $");
#include "ssh.h"
#include "rsa.h"
@ -65,7 +65,7 @@ ssh_get_authentication_socket()
* ssh_get_authentication_socket().
*/
void
void
ssh_close_authentication_socket(int sock)
{
if (getenv(SSH_AUTHSOCKET_ENV_NAME))
@ -109,7 +109,7 @@ ssh_get_authentication_connection()
* memory.
*/
void
void
ssh_close_authentication_connection(AuthenticationConnection *ac)
{
buffer_free(&ac->packet);
@ -218,8 +218,8 @@ ssh_get_next_identity(AuthenticationConnection *auth,
*comment = buffer_get_string(&auth->identities, NULL);
if (bits != BN_num_bits(n))
error("Warning: identity keysize mismatch: actual %d, announced %u",
BN_num_bits(n), bits);
log("Warning: identity keysize mismatch: actual %d, announced %u",
BN_num_bits(n), bits);
/* Decrement the number of remaining entries. */
auth->howmany--;
@ -339,7 +339,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
* be used by normal applications.
*/
int
int
ssh_add_identity(AuthenticationConnection *auth,
RSA * key, const char *comment)
{
@ -427,7 +427,7 @@ ssh_add_identity(AuthenticationConnection *auth,
* meant to be used by normal applications.
*/
int
int
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
{
Buffer buffer;
@ -510,7 +510,7 @@ ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
* by normal applications.
*/
int
int
ssh_remove_all_identities(AuthenticationConnection *auth)
{
Buffer buffer;

View File

@ -1,29 +1,35 @@
/*
*
*
* authfile.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Mon Mar 27 03:52:05 1995 ylo
*
*
* This file contains functions for reading and writing identity files, and
* for reading the passphrase from the user.
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: authfile.c,v 1.11 1999/12/06 19:11:15 deraadt Exp $");
RCSID("$Id: authfile.c,v 1.16 2000/04/26 21:28:32 markus Exp $");
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include "xmalloc.h"
#include "buffer.h"
#include "bufaux.h"
#include "cipher.h"
#include "ssh.h"
#include "key.h"
/* Version identification string for identity files. */
#define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n"
@ -36,8 +42,8 @@ RCSID("$Id: authfile.c,v 1.11 1999/12/06 19:11:15 deraadt Exp $");
*/
int
save_private_key(const char *filename, const char *passphrase,
RSA *key, const char *comment)
save_private_key_rsa(const char *filename, const char *passphrase,
RSA *key, const char *comment)
{
Buffer buffer, encrypted;
char buf[100], *cp;
@ -102,7 +108,7 @@ save_private_key(const char *filename, const char *passphrase,
/* Allocate space for the private part of the key in the buffer. */
buffer_append_space(&encrypted, &cp, buffer_len(&buffer));
cipher_set_key_string(&cipher, cipher_type, passphrase, 1);
cipher_set_key_string(&cipher, cipher_type, passphrase);
cipher_encrypt(&cipher, (unsigned char *) cp,
(unsigned char *) buffer_ptr(&buffer),
buffer_len(&buffer));
@ -129,6 +135,63 @@ save_private_key(const char *filename, const char *passphrase,
return 1;
}
/* save DSA key in OpenSSL PEM format */
int
save_private_key_dsa(const char *filename, const char *passphrase,
DSA *dsa, const char *comment)
{
FILE *fp;
int fd;
int success = 1;
int len = strlen(passphrase);
if (len > 0 && len <= 4) {
error("passphrase too short: %d bytes", len);
errno = 0;
return 0;
}
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (fd < 0) {
debug("open %s failed", filename);
return 0;
}
fp = fdopen(fd, "w");
if (fp == NULL ) {
debug("fdopen %s failed", filename);
close(fd);
return 0;
}
if (len > 0) {
if (!PEM_write_DSAPrivateKey(fp, dsa, EVP_des_ede3_cbc(),
(char *)passphrase, strlen(passphrase), NULL, NULL))
success = 0;
} else {
if (!PEM_write_DSAPrivateKey(fp, dsa, NULL,
NULL, 0, NULL, NULL))
success = 0;
}
fclose(fp);
return success;
}
int
save_private_key(const char *filename, const char *passphrase, Key *key,
const char *comment)
{
switch (key->type) {
case KEY_RSA:
return save_private_key_rsa(filename, passphrase, key->rsa, comment);
break;
case KEY_DSA:
return save_private_key_dsa(filename, passphrase, key->dsa, comment);
break;
default:
break;
}
return 0;
}
/*
* Loads the public part of the key file. Returns 0 if an error was
* encountered (the file does not exist or is not readable), and non-zero
@ -136,8 +199,7 @@ save_private_key(const char *filename, const char *passphrase,
*/
int
load_public_key(const char *filename, RSA * pub,
char **comment_return)
load_public_key_rsa(const char *filename, RSA * pub, char **comment_return)
{
int fd, i;
off_t len;
@ -155,7 +217,7 @@ load_public_key(const char *filename, RSA * pub,
if (read(fd, cp, (size_t) len) != (size_t) len) {
debug("Read from key file %.200s failed: %.100s", filename,
strerror(errno));
strerror(errno));
buffer_free(&buffer);
close(fd);
return 0;
@ -184,9 +246,13 @@ load_public_key(const char *filename, RSA * pub,
/* Read the public key from the buffer. */
buffer_get_int(&buffer);
pub->n = BN_new();
/* XXX alloc */
if (pub->n == NULL)
pub->n = BN_new();
buffer_get_bignum(&buffer, pub->n);
pub->e = BN_new();
/* 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);
@ -197,6 +263,20 @@ load_public_key(const char *filename, RSA * pub,
return 1;
}
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
@ -205,35 +285,17 @@ load_public_key(const char *filename, RSA * pub,
*/
int
load_private_key(const char *filename, const char *passphrase,
RSA * prv, char **comment_return)
load_private_key_rsa(int fd, const char *filename,
const char *passphrase, RSA * prv, char **comment_return)
{
int fd, i, check1, check2, cipher_type;
int i, check1, check2, cipher_type;
off_t len;
Buffer buffer, decrypted;
char *cp;
CipherContext cipher;
BN_CTX *ctx;
BIGNUM *aux;
struct stat st;
fd = open(filename, O_RDONLY);
if (fd < 0)
return 0;
/* check owner and modes */
if (fstat(fd, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != getuid()) ||
(st.st_mode & 077) != 0) {
close(fd);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("Bad ownership or mode(0%3.3o) for '%s'.",
st.st_mode & 0777, filename);
error("It is recommended that your private key files are NOT accessible by others.");
return 0;
}
len = lseek(fd, (off_t) 0, SEEK_END);
lseek(fd, (off_t) 0, SEEK_SET);
@ -281,7 +343,7 @@ load_private_key(const char *filename, const char *passphrase,
xfree(buffer_get_string(&buffer, NULL));
/* Check that it is a supported cipher. */
if (((cipher_mask() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &
(1 << cipher_type)) == 0) {
debug("Unsupported cipher %.100s used in key file %.200s.",
cipher_name(cipher_type), filename);
@ -293,7 +355,7 @@ load_private_key(const char *filename, const char *passphrase,
buffer_append_space(&decrypted, &cp, buffer_len(&buffer));
/* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
cipher_set_key_string(&cipher, cipher_type, passphrase, 0);
cipher_set_key_string(&cipher, cipher_type, passphrase);
cipher_decrypt(&cipher, (unsigned char *) cp,
(unsigned char *) buffer_ptr(&buffer),
buffer_len(&buffer));
@ -310,7 +372,9 @@ load_private_key(const char *filename, const char *passphrase,
buffer_free(&decrypted);
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;
@ -344,3 +408,87 @@ load_private_key(const char *filename, const char *passphrase,
return 1;
}
int
load_private_key_dsa(int fd, const char *passphrase, Key *k, char **comment_return)
{
DSA *dsa;
BIO *in;
FILE *fp;
in = BIO_new(BIO_s_file());
if (in == NULL) {
error("BIO_new failed");
return 0;
}
fp = fdopen(fd, "r");
if (fp == NULL) {
error("fdopen failed");
return 0;
}
BIO_set_fp(in, fp, BIO_NOCLOSE);
dsa = PEM_read_bio_DSAPrivateKey(in, NULL, NULL, (char *)passphrase);
if (dsa == NULL) {
debug("PEM_read_bio_DSAPrivateKey failed");
} else {
/* replace k->dsa with loaded key */
DSA_free(k->dsa);
k->dsa = dsa;
}
BIO_free(in);
fclose(fp);
if (comment_return)
*comment_return = xstrdup("dsa w/o comment");
debug("read DSA private key done");
#ifdef DEBUG_DSS
DSA_print_fp(stderr, dsa, 8);
#endif
return dsa != NULL ? 1 : 0;
}
int
load_private_key(const char *filename, const char *passphrase, Key *key,
char **comment_return)
{
int fd;
int ret = 0;
struct stat st;
fd = open(filename, O_RDONLY);
if (fd < 0)
return 0;
/* check owner and modes */
if (fstat(fd, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != getuid()) ||
(st.st_mode & 077) != 0) {
close(fd);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("Bad ownership or mode(0%3.3o) for '%s'.",
st.st_mode & 0777, filename);
error("It is recommended that your private key files are NOT accessible by others.");
return 0;
}
switch (key->type) {
case KEY_RSA:
if (key->rsa->e != NULL) {
BN_clear_free(key->rsa->e);
key->rsa->e = NULL;
}
if (key->rsa->n != NULL) {
BN_clear_free(key->rsa->n);
key->rsa->n = NULL;
}
ret = load_private_key_rsa(fd, filename, passphrase,
key->rsa, comment_return);
break;
case KEY_DSA:
ret = load_private_key_dsa(fd, passphrase, key, comment_return);
default:
break;
}
close(fd);
return ret;
}

View File

@ -1,22 +1,24 @@
/*
*
*
* bufaux.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Wed Mar 29 02:24:47 1995 ylo
*
*
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
*
* SSH2 packet format added by Markus Friedl
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: bufaux.c,v 1.8 2000/03/16 20:56:14 markus Exp $");
RCSID("$Id: bufaux.c,v 1.11 2000/04/14 10:30:30 markus Exp $");
#include "ssh.h"
#include <openssl/bn.h>
@ -76,10 +78,54 @@ buffer_get_bignum(Buffer *buffer, BIGNUM *value)
return 2 + bytes;
}
/*
* Stores an BIGNUM in the buffer in SSH2 format.
*/
void
buffer_put_bignum2(Buffer *buffer, BIGNUM *value)
{
int bytes = BN_num_bytes(value) + 1;
unsigned char *buf = xmalloc(bytes);
int oi;
int hasnohigh = 0;
buf[0] = '\0';
/* Get the value of in binary */
oi = BN_bn2bin(value, buf+1);
if (oi != bytes-1)
fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d",
oi, bytes);
hasnohigh = (buf[1] & 0x80) ? 0 : 1;
if (value->neg) {
/**XXX should be two's-complement */
int i, carry;
unsigned char *uc = buf;
log("negativ!");
for(i = bytes-1, carry = 1; i>=0; i--) {
uc[i] ^= 0xff;
if(carry)
carry = !++uc[i];
}
}
buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
memset(buf, 0, bytes);
xfree(buf);
}
int
buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
{
/**XXX should be two's-complement */
int len;
unsigned char *bin = (unsigned char *)buffer_get_string(buffer, (unsigned int *)&len);
BN_bin2bn(bin, len, value);
xfree(bin);
return len;
}
/*
* Returns an integer from the buffer (4 bytes, msb first).
*/
unsigned int
unsigned int
buffer_get_int(Buffer *buffer)
{
unsigned char buf[4];
@ -90,7 +136,7 @@ buffer_get_int(Buffer *buffer)
/*
* Stores an integer in the buffer in 4 bytes, msb first.
*/
void
void
buffer_put_int(Buffer *buffer, unsigned int value)
{
char buf[4];
@ -130,17 +176,22 @@ buffer_get_string(Buffer *buffer, unsigned int *length_ptr)
/*
* Stores and arbitrary binary string in the buffer.
*/
void
void
buffer_put_string(Buffer *buffer, const void *buf, unsigned int len)
{
buffer_put_int(buffer, len);
buffer_append(buffer, buf, len);
}
void
buffer_put_cstring(Buffer *buffer, const char *s)
{
buffer_put_string(buffer, s, strlen(s));
}
/*
* Returns a character from the buffer (0 - 255).
*/
int
int
buffer_get_char(Buffer *buffer)
{
char ch;
@ -151,7 +202,7 @@ buffer_get_char(Buffer *buffer)
/*
* Stores a character in the buffer.
*/
void
void
buffer_put_char(Buffer *buffer, int value)
{
char ch = value;

View File

@ -1,27 +1,30 @@
/*
*
*
* cipher.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Wed Apr 19 17:41:39 1995 ylo
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: cipher.c,v 1.20 2000/03/22 09:55:10 markus Exp $");
RCSID("$Id: cipher.c,v 1.26 2000/04/14 10:30:30 markus Exp $");
#include "ssh.h"
#include "cipher.h"
#include "xmalloc.h"
#include <openssl/md5.h>
/*
* What kind of tripple DES are these 2 routines?
* This is used by SSH1:
*
* What kind of triple DES are these 2 routines?
*
* Why is there a redundant initialization vector?
*
@ -76,7 +79,7 @@ SSH_3CBC_DECRYPT(des_key_schedule ks1,
}
/*
* SSH uses a variation on Blowfish, all bytes must be swapped before
* SSH1 uses a variation on Blowfish, all bytes must be swapped before
* and after encryption/decryption. Thus the swap_bytes stuff (yuk).
*/
static void
@ -117,7 +120,12 @@ static char *cipher_names[] =
"3des",
"tss",
"rc4",
"blowfish"
"blowfish",
"reserved",
"blowfish-cbc",
"3des-cbc",
"arcfour",
"cast128-cbc"
};
/*
@ -126,14 +134,29 @@ static char *cipher_names[] =
* supported cipher.
*/
unsigned int
cipher_mask()
unsigned int
cipher_mask1()
{
unsigned int mask = 0;
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
mask |= 1 << SSH_CIPHER_BLOWFISH;
return mask;
}
unsigned int
cipher_mask2()
{
unsigned int mask = 0;
mask |= 1 << SSH_CIPHER_BLOWFISH_CBC;
mask |= 1 << SSH_CIPHER_3DES_CBC;
mask |= 1 << SSH_CIPHER_ARCFOUR;
mask |= 1 << SSH_CIPHER_CAST128_CBC;
return mask;
}
unsigned int
cipher_mask()
{
return cipher_mask1() | cipher_mask2();
}
/* Returns the name of the cipher. */
@ -142,10 +165,34 @@ cipher_name(int cipher)
{
if (cipher < 0 || cipher >= sizeof(cipher_names) / sizeof(cipher_names[0]) ||
cipher_names[cipher] == NULL)
fatal("cipher_name: bad cipher number: %d", cipher);
fatal("cipher_name: bad cipher name: %d", cipher);
return cipher_names[cipher];
}
/* Returns 1 if the name of the ciphers are valid. */
#define CIPHER_SEP ","
int
ciphers_valid(const char *names)
{
char *ciphers;
char *p;
int i;
if (strcmp(names, "") == 0)
return 0;
ciphers = xstrdup(names);
for ((p = strtok(ciphers, CIPHER_SEP)); p; (p = strtok(NULL, CIPHER_SEP))) {
i = cipher_number(p);
if (i == -1 || !(cipher_mask2() & (1 << i))) {
xfree(ciphers);
return 0;
}
}
xfree(ciphers);
return 1;
}
/*
* Parses the name of the cipher. Returns the number of the corresponding
* cipher, or -1 on error.
@ -167,9 +214,8 @@ cipher_number(const char *name)
* passphrase and using the resulting 16 bytes as the key.
*/
void
cipher_set_key_string(CipherContext *context, int cipher,
const char *passphrase, int for_encryption)
void
cipher_set_key_string(CipherContext *context, int cipher, const char *passphrase)
{
MD5_CTX md;
unsigned char digest[16];
@ -178,7 +224,7 @@ cipher_set_key_string(CipherContext *context, int cipher,
MD5_Update(&md, (const unsigned char *) passphrase, strlen(passphrase));
MD5_Final(digest, &md);
cipher_set_key(context, cipher, digest, 16, for_encryption);
cipher_set_key(context, cipher, digest, 16);
memset(digest, 0, sizeof(digest));
memset(&md, 0, sizeof(md));
@ -186,9 +232,9 @@ cipher_set_key_string(CipherContext *context, int cipher,
/* Selects the cipher to use and sets the key. */
void
cipher_set_key(CipherContext *context, int cipher,
const unsigned char *key, int keylen, int for_encryption)
void
cipher_set_key(CipherContext *context, int cipher, const unsigned char *key,
int keylen)
{
unsigned char padded[32];
@ -228,19 +274,86 @@ cipher_set_key(CipherContext *context, int cipher,
break;
case SSH_CIPHER_BLOWFISH:
if (keylen < 16)
error("Key length %d is insufficient for blowfish.", keylen);
BF_set_key(&context->u.bf.key, keylen, padded);
memset(context->u.bf.iv, 0, 8);
break;
case SSH_CIPHER_3DES_CBC:
case SSH_CIPHER_BLOWFISH_CBC:
case SSH_CIPHER_ARCFOUR:
case SSH_CIPHER_CAST128_CBC:
fatal("cipher_set_key: illegal cipher: %s", cipher_name(cipher));
break;
default:
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
}
memset(padded, 0, sizeof(padded));
}
void
cipher_set_key_iv(CipherContext * context, int cipher,
const unsigned char *key, int keylen,
const unsigned char *iv, int ivlen)
{
/* Set cipher type. */
context->type = cipher;
/* Initialize the initialization vector. */
switch (cipher) {
case SSH_CIPHER_NONE:
break;
case SSH_CIPHER_3DES:
case SSH_CIPHER_BLOWFISH:
fatal("cipher_set_key_iv: illegal cipher: %s", cipher_name(cipher));
break;
case SSH_CIPHER_3DES_CBC:
if (keylen < 24)
error("Key length %d is insufficient for 3des-cbc.", keylen);
des_set_key((void *) key, context->u.des3.key1);
des_set_key((void *) (key+8), context->u.des3.key2);
des_set_key((void *) (key+16), context->u.des3.key3);
if (ivlen < 8)
error("IV length %d is insufficient for 3des-cbc.", ivlen);
memcpy(context->u.des3.iv3, (char *)iv, 8);
break;
case SSH_CIPHER_BLOWFISH_CBC:
if (keylen < 16)
error("Key length %d is insufficient for blowfish.", keylen);
if (ivlen < 8)
error("IV length %d is insufficient for blowfish.", ivlen);
BF_set_key(&context->u.bf.key, keylen, (unsigned char *)key);
memcpy(context->u.bf.iv, (char *)iv, 8);
break;
case SSH_CIPHER_ARCFOUR:
if (keylen < 16)
error("Key length %d is insufficient for arcfour.", keylen);
RC4_set_key(&context->u.rc4, keylen, (unsigned char *)key);
break;
case SSH_CIPHER_CAST128_CBC:
if (keylen < 16)
error("Key length %d is insufficient for cast128.", keylen);
if (ivlen < 8)
error("IV length %d is insufficient for cast128.", ivlen);
CAST_set_key(&context->u.cast.key, keylen, (unsigned char *) key);
memcpy(context->u.cast.iv, (char *)iv, 8);
break;
default:
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
}
}
/* Encrypts data using the cipher. */
void
void
cipher_encrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len)
{
@ -262,11 +375,32 @@ cipher_encrypt(CipherContext *context, unsigned char *dest,
case SSH_CIPHER_BLOWFISH:
swap_bytes(src, dest, len);
BF_cbc_encrypt(dest, dest, len,
&context->u.bf.key, context->u.bf.iv,
&context->u.bf.key, context->u.bf.iv,
BF_ENCRYPT);
swap_bytes(dest, dest, len);
break;
case SSH_CIPHER_BLOWFISH_CBC:
BF_cbc_encrypt((void *)src, dest, len,
&context->u.bf.key, context->u.bf.iv,
BF_ENCRYPT);
break;
case SSH_CIPHER_3DES_CBC:
des_ede3_cbc_encrypt(src, dest, len,
context->u.des3.key1, context->u.des3.key2,
context->u.des3.key3, &context->u.des3.iv3, DES_ENCRYPT);
break;
case SSH_CIPHER_ARCFOUR:
RC4(&context->u.rc4, len, (unsigned char *)src, dest);
break;
case SSH_CIPHER_CAST128_CBC:
CAST_cbc_encrypt(src, dest, len,
&context->u.cast.key, context->u.cast.iv, CAST_ENCRYPT);
break;
default:
fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type));
}
@ -274,7 +408,7 @@ cipher_encrypt(CipherContext *context, unsigned char *dest,
/* Decrypts data using the cipher. */
void
void
cipher_decrypt(CipherContext *context, unsigned char *dest,
const unsigned char *src, unsigned int len)
{
@ -301,6 +435,27 @@ cipher_decrypt(CipherContext *context, unsigned char *dest,
swap_bytes(dest, dest, len);
break;
case SSH_CIPHER_BLOWFISH_CBC:
BF_cbc_encrypt((void *) src, dest, len,
&context->u.bf.key, context->u.bf.iv,
BF_DECRYPT);
break;
case SSH_CIPHER_3DES_CBC:
des_ede3_cbc_encrypt(src, dest, len,
context->u.des3.key1, context->u.des3.key2,
context->u.des3.key3, &context->u.des3.iv3, DES_DECRYPT);
break;
case SSH_CIPHER_ARCFOUR:
RC4(&context->u.rc4, len, (unsigned char *)src, dest);
break;
case SSH_CIPHER_CAST128_CBC:
CAST_cbc_encrypt(src, dest, len,
&context->u.cast.key, context->u.cast.iv, CAST_DECRYPT);
break;
default:
fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
}

View File

@ -1,27 +1,30 @@
/*
*
*
* cipher.h
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Wed Apr 19 16:50:42 1995 ylo
*
*
* $FreeBSD$
*/
/* RCSID("$Id: cipher.h,v 1.11 2000/03/22 09:55:10 markus Exp $"); */
/* RCSID("$Id: cipher.h,v 1.17 2000/05/08 17:12:15 markus Exp $"); */
#ifndef CIPHER_H
#define CIPHER_H
#include <openssl/des.h>
#include <openssl/blowfish.h>
#include <openssl/rc4.h>
#include <openssl/cast.h>
/* Cipher types. New types can be added, but old types should not be removed
for compatibility. The maximum allowed value is 31. */
#define SSH_CIPHER_ILLEGAL -2 /* No valid cipher selected. */
#define SSH_CIPHER_NOT_SET -1 /* None selected (invalid number). */
#define SSH_CIPHER_NONE 0 /* no encryption */
#define SSH_CIPHER_IDEA 1 /* IDEA CFB */
@ -30,6 +33,13 @@
#define SSH_CIPHER_BROKEN_TSS 4 /* TRI's Simple Stream encryption CBC */
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
#define SSH_CIPHER_BLOWFISH 6
#define SSH_CIPHER_RESERVED 7
/* these ciphers are used in SSH2: */
#define SSH_CIPHER_BLOWFISH_CBC 8
#define SSH_CIPHER_3DES_CBC 9
#define SSH_CIPHER_ARCFOUR 10 /* Alleged RC4 */
#define SSH_CIPHER_CAST128_CBC 11
typedef struct {
unsigned int type;
@ -45,6 +55,11 @@ typedef struct {
struct bf_key_st key;
unsigned char iv[8];
} bf;
struct {
CAST_KEY key;
unsigned char iv[8];
} cast;
RC4_KEY rc4;
} u;
} CipherContext;
/*
@ -53,6 +68,8 @@ typedef struct {
* supported cipher.
*/
unsigned int cipher_mask();
unsigned int cipher_mask1();
unsigned int cipher_mask2();
/* Returns the name of the cipher. */
const char *cipher_name(int cipher);
@ -63,29 +80,36 @@ const char *cipher_name(int cipher);
*/
int cipher_number(const char *name);
/* returns 1 if all ciphers are supported (ssh2 only) */
int ciphers_valid(const char *names);
/*
* Selects the cipher to use and sets the key. If for_encryption is true,
* the key is setup for encryption; otherwise it is setup for decryption.
*/
void
void
cipher_set_key(CipherContext * context, int cipher,
const unsigned char *key, int keylen, int for_encryption);
const unsigned char *key, int keylen);
void
cipher_set_key_iv(CipherContext * context, int cipher,
const unsigned char *key, int keylen,
const unsigned char *iv, int ivlen);
/*
* Sets key for the cipher by computing the MD5 checksum of the passphrase,
* and using the resulting 16 bytes as the key.
*/
void
void
cipher_set_key_string(CipherContext * context, int cipher,
const char *passphrase, int for_encryption);
const char *passphrase);
/* Encrypts data using the cipher. */
void
void
cipher_encrypt(CipherContext * context, unsigned char *dest,
const unsigned char *src, unsigned int len);
/* Decrypts data using the cipher. */
void
void
cipher_decrypt(CipherContext * context, unsigned char *dest,
const unsigned char *src, unsigned int len);

View File

@ -30,7 +30,7 @@
*/
#include "includes.h"
RCSID("$Id: fingerprint.c,v 1.5 2000/03/16 20:56:14 markus Exp $");
RCSID("$Id: fingerprint.c,v 1.6 2000/04/12 09:39:10 markus Exp $");
#include "ssh.h"
#include "xmalloc.h"

View File

@ -1,21 +1,21 @@
/*
*
*
* hostfile.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Thu Jun 29 07:10:56 1995 ylo
*
*
* Functions for manipulating the known hosts files.
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$OpenBSD: hostfile.c,v 1.14 2000/03/23 22:15:33 markus Exp $");
RCSID("$OpenBSD: hostfile.c,v 1.18 2000/04/29 18:11:52 markus Exp $");
#include "packet.h"
#include "match.h"
@ -40,13 +40,8 @@ hostfile_read_key(char **cpp, unsigned int *bitsp, Key *ret)
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
/* Get number of bits. */
if (*cp < '0' || *cp > '9')
return 0; /* Bad bit count... */
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
bits = 10 * bits + *cp - '0';
if (!key_read(ret, bits, &cp))
bits = key_read(ret, &cp);
if (bits == 0)
return 0;
/* Skip trailing whitespace. */
@ -76,10 +71,10 @@ hostfile_check_key(int bits, Key *key, const char *host, const char *filename, i
if (key == NULL || key->type != KEY_RSA || key->rsa == NULL)
return 1;
if (bits != BN_num_bits(key->rsa->n)) {
error("Warning: %s, line %d: keysize mismatch for host %s: "
log("Warning: %s, line %d: keysize mismatch for host %s: "
"actual %d vs. announced %d.",
filename, linenum, host, BN_num_bits(key->rsa->n), bits);
error("Warning: replace %d with %d in %s, line %d.",
log("Warning: replace %d with %d in %s, line %d.",
bits, BN_num_bits(key->rsa->n), filename, linenum);
}
return 1;
@ -183,24 +178,18 @@ add_host_to_hostfile(const char *filename, const char *host, Key *key)
{
FILE *f;
int success = 0;
if (key == NULL)
return 1;
/* Open the file for appending. */
return 1; /* XXX ? */
f = fopen(filename, "a");
if (!f)
return 0;
fprintf(f, "%s ", host);
if (key_write(key, f)) {
fprintf(f, "\n");
success = 1;
} else {
error("add_host_to_hostfile: saving key failed");
error("add_host_to_hostfile: saving key in %s failed", filename);
}
/* Close the file. */
fprintf(f, "\n");
fclose(f);
return success;
}

View File

@ -1,16 +1,16 @@
/*
*
*
* includes.h
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Thu Mar 23 16:29:37 1995 ylo
*
*
* This file includes most of the needed system headers.
*
*
* $FreeBSD$
*/
@ -63,34 +63,7 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
/*
* Define this to use pipes instead of socketpairs for communicating with the
* client program. Socketpairs do not seem to work on all systems.
* Although pipes are bi-directional in FreeBSD, using pipes here will
* make <stdin> uni-directional !
*/
/* #define USE_PIPES 1 */
#if defined(__FreeBSD__) && __FreeBSD__ <= 3
/*
* Data types.
*/
typedef u_char sa_family_t;
typedef u_int32_t socklen_t;
/*
* bsd-api-new-02a: protocol-independent placeholder for socket addresses
*/
#define _SS_MAXSIZE 128
#define _SS_ALIGNSIZE (sizeof(int64_t))
#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(u_char) * 2)
#define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(u_char) * 2 - \
_SS_PAD1SIZE - _SS_ALIGNSIZE)
struct sockaddr_storage {
u_char ss_len; /* address length */
sa_family_t ss_family; /* address family */
char __ss_pad1[_SS_PAD1SIZE];
int64_t __ss_align; /* force desired structure storage alignment */
char __ss_pad2[_SS_PAD2SIZE];
};
#endif
#define USE_PIPES 1
#endif /* INCLUDES_H */

View File

@ -40,6 +40,10 @@
#include <openssl/evp.h>
#include "xmalloc.h"
#include "key.h"
#include "dsa.h"
#include "uuencode.h"
#define SSH_DSS "ssh-dss"
Key *
key_new(int type)
@ -49,6 +53,8 @@ key_new(int type)
DSA *dsa;
k = xmalloc(sizeof(*k));
k->type = type;
k->dsa = NULL;
k->rsa = NULL;
switch (k->type) {
case KEY_RSA:
rsa = RSA_new();
@ -65,8 +71,6 @@ key_new(int type)
k->dsa = dsa;
break;
case KEY_EMPTY:
k->dsa = NULL;
k->rsa = NULL;
break;
default:
fatal("key_new: bad key type %d", k->type);
@ -113,7 +117,7 @@ key_equal(Key *a, Key *b)
BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
break;
default:
fatal("key_free: bad key type %d", a->type);
fatal("key_equal: bad key type %d", a->type);
break;
}
return 0;
@ -129,46 +133,37 @@ char *
key_fingerprint(Key *k)
{
static char retval[80];
unsigned char *buf = NULL;
unsigned char *blob = NULL;
int len = 0;
int nlen, elen, plen, qlen, glen, publen;
int nlen, elen;
switch (k->type) {
case KEY_RSA:
nlen = BN_num_bytes(k->rsa->n);
elen = BN_num_bytes(k->rsa->e);
len = nlen + elen;
buf = xmalloc(len);
BN_bn2bin(k->rsa->n, buf);
BN_bn2bin(k->rsa->e, buf + nlen);
blob = xmalloc(len);
BN_bn2bin(k->rsa->n, blob);
BN_bn2bin(k->rsa->e, blob + nlen);
break;
case KEY_DSA:
plen = BN_num_bytes(k->dsa->p);
qlen = BN_num_bytes(k->dsa->q);
glen = BN_num_bytes(k->dsa->g);
publen = BN_num_bytes(k->dsa->pub_key);
len = qlen + qlen + glen + publen;
buf = xmalloc(len);
BN_bn2bin(k->dsa->p, buf);
BN_bn2bin(k->dsa->q, buf + plen);
BN_bn2bin(k->dsa->g, buf + plen + qlen);
BN_bn2bin(k->dsa->pub_key , buf + plen + qlen + glen);
dsa_make_key_blob(k, &blob, &len);
break;
default:
fatal("key_fingerprint: bad key type %d", k->type);
break;
}
if (buf != NULL) {
if (blob != NULL) {
unsigned char d[16];
EVP_MD_CTX md;
EVP_DigestInit(&md, EVP_md5());
EVP_DigestUpdate(&md, buf, len);
EVP_DigestUpdate(&md, blob, len);
EVP_DigestFinal(&md, d, NULL);
snprintf(retval, sizeof(retval), FPRINT,
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
memset(buf, 0, len);
xfree(buf);
memset(blob, 0, len);
xfree(blob);
}
return retval;
}
@ -228,13 +223,27 @@ write_bignum(FILE *f, BIGNUM *num)
free(buf);
return 1;
}
int
key_read(Key *ret, unsigned int bits, char **cpp)
unsigned int
key_read(Key *ret, char **cpp)
{
Key *k;
unsigned int bits = 0;
char *cp;
int len, n;
unsigned char *blob;
cp = *cpp;
switch(ret->type) {
case KEY_RSA:
/* Get number of bits. */
if (*cp < '0' || *cp > '9')
return 0; /* Bad bit count... */
for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
bits = 10 * bits + *cp - '0';
if (bits == 0)
return 0;
*cpp = cp;
/* Get public exponent, public modulus. */
if (!read_bignum(cpp, ret->rsa->e))
return 0;
@ -242,22 +251,36 @@ key_read(Key *ret, unsigned int bits, char **cpp)
return 0;
break;
case KEY_DSA:
if (bits != 0)
if (strncmp(cp, SSH_DSS " ", 7) != 0)
return 0;
if (!read_bignum(cpp, ret->dsa->p))
cp += 7;
len = 2*strlen(cp);
blob = xmalloc(len);
n = uudecode(cp, blob, len);
if (n < 0) {
error("uudecode %s failed", cp);
return 0;
if (!read_bignum(cpp, ret->dsa->q))
return 0;
if (!read_bignum(cpp, ret->dsa->g))
return 0;
if (!read_bignum(cpp, ret->dsa->pub_key))
}
k = dsa_key_from_blob(blob, n);
if (k == NULL)
return 0;
xfree(blob);
if (ret->dsa != NULL)
DSA_free(ret->dsa);
ret->dsa = k->dsa;
k->dsa = NULL;
key_free(k);
bits = BN_num_bits(ret->dsa->p);
cp = strchr(cp, '=');
if (cp == NULL)
return 0;
*cpp = cp + 1;
break;
default:
fatal("bad key type: %d", ret->type);
fatal("key_read: bad key type: %d", ret->type);
break;
}
return 1;
return bits;
}
int
key_write(Key *key, FILE *f)
@ -276,17 +299,30 @@ key_write(Key *key, FILE *f)
error("key_write: failed for RSA key");
}
} else if (key->type == KEY_DSA && key->dsa != NULL) {
/* bits == 0 means DSA key */
bits = 0;
fprintf(f, "%u", bits);
if (write_bignum(f, key->dsa->p) &&
write_bignum(f, key->dsa->q) &&
write_bignum(f, key->dsa->g) &&
write_bignum(f, key->dsa->pub_key)) {
int len, n;
unsigned char *blob, *uu;
dsa_make_key_blob(key, &blob, &len);
uu = xmalloc(2*len);
n = uuencode(blob, len, uu, 2*len);
if (n > 0) {
fprintf(f, "%s %s", SSH_DSS, uu);
success = 1;
} else {
error("key_write: failed for DSA key");
}
xfree(blob);
xfree(uu);
}
return success;
}
char *
key_type(Key *k)
{
switch (k->type) {
case KEY_RSA:
return "RSA";
break;
case KEY_DSA:
return "DSA";
break;
}
return "unknown";
}

View File

@ -1,25 +1,25 @@
/*
*
*
* login.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Fri Mar 24 14:51:08 1995 ylo
*
*
* This file performs some of the things login(1) normally does. We cannot
* easily use something like login -p -h host -f user, because there are
* several different logins around, and it is hard to determined what kind of
* login the current system has. Also, we want to be able to execute commands
* on a tty.
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: login.c,v 1.11 2000/01/04 00:07:59 markus Exp $");
RCSID("$Id: login.c,v 1.13 2000/04/19 07:05:49 deraadt Exp $");
#ifdef __FreeBSD__
#include <libutil.h>
@ -40,7 +40,7 @@ RCSID("$Id: login.c,v 1.11 2000/01/04 00:07:59 markus Exp $");
* is found). The name of the host used last time is returned in buf.
*/
unsigned long
unsigned long
get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize)
{
@ -72,8 +72,8 @@ get_last_login_time(uid_t uid, const char *logname,
* were more standardized.
*/
void
record_login(int pid, const char *ttyname, const char *user, uid_t uid,
void
record_login(pid_t pid, const char *ttyname, const char *user, uid_t uid,
const char *host, struct sockaddr * addr)
{
int fd;
@ -120,8 +120,8 @@ record_login(int pid, const char *ttyname, const char *user, uid_t uid,
/* Records that the user has logged out. */
void
record_logout(int pid, const char *ttyname)
void
record_logout(pid_t pid, const char *ttyname)
{
const char *line = ttyname + 5; /* /dev/ttyq8 -> ttyq8 */
if (logout(line))

View File

@ -1,22 +1,22 @@
/*
*
*
* mpaux.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Sun Jul 16 04:29:30 1995 ylo
*
*
* This file contains various auxiliary functions related to multiple
* precision integers.
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: mpaux.c,v 1.9 1999/12/08 22:37:42 markus Exp $");
RCSID("$Id: mpaux.c,v 1.12 2000/04/14 10:30:32 markus Exp $");
#include <openssl/bn.h>
#include "getput.h"
@ -26,9 +26,9 @@ RCSID("$Id: mpaux.c,v 1.9 1999/12/08 22:37:42 markus Exp $");
void
compute_session_id(unsigned char session_id[16],
unsigned char cookie[8],
BIGNUM* host_key_n,
BIGNUM* session_key_n)
unsigned char cookie[8],
BIGNUM* host_key_n,
BIGNUM* session_key_n)
{
unsigned int host_key_bytes = BN_num_bytes(host_key_n);
unsigned int session_key_bytes = BN_num_bytes(session_key_n);

View File

@ -1,20 +1,20 @@
/*
*
*
* packet.h
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Sat Mar 18 02:02:14 1995 ylo
*
*
* Interface for the packet protocol functions.
*
*
* $FreeBSD$
*/
/* RCSID("$Id: packet.h,v 1.10 2000/03/16 20:56:14 markus Exp $"); */
/* RCSID("$Id: packet.h,v 1.15 2000/04/14 10:30:32 markus Exp $"); */
#ifndef PACKET_H
#define PACKET_H
@ -48,7 +48,7 @@ void packet_close(void);
* key is used for both sending and reception. However, both directions are
* 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,
int cipher_type);
@ -84,9 +84,12 @@ void packet_put_int(unsigned int value);
/* Appends an arbitrary precision integer to packet data. */
void packet_put_bignum(BIGNUM * value);
void packet_put_bignum2(BIGNUM * value);
/* Appends a string to packet data. */
void packet_put_string(const char *buf, unsigned int len);
void packet_put_cstring(const char *str);
void packet_put_raw(const char *buf, unsigned int len);
/*
* Finalizes and sends the packet. If the encryption key has been set,
@ -130,6 +133,8 @@ unsigned int packet_get_int(void);
* must have been initialized before this call.
*/
void packet_get_bignum(BIGNUM * value, int *length_ptr);
void packet_get_bignum2(BIGNUM * value, int *length_ptr);
char *packet_get_raw(int *length_ptr);
/*
* Returns a string from the packet data. The string is allocated using
@ -192,8 +197,24 @@ do { \
} \
} while (0)
#define packet_done() \
do { \
int _len = packet_remaining(); \
if (_len > 0) { \
log("Packet integrity error (%d bytes remaining) at %s:%d", \
_len ,__FILE__, __LINE__); \
packet_disconnect("Packet integrity error."); \
} \
} while (0)
/* remote host is connected via a socket/ipv4 */
int packet_connection_is_on_socket(void);
int packet_connection_is_ipv4(void);
/* enable SSH2 packet format */
void packet_set_ssh2_format(void);
/* returns remaining payload bytes */
int packet_remaining(void);
#endif /* PACKET_H */

View File

@ -1,27 +1,27 @@
/*
*
*
* pty.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Fri Mar 17 04:37:25 1995 ylo
*
*
* Allocating a pseudo-terminal, and making it the controlling tty.
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: pty.c,v 1.12 2000/02/15 16:52:58 markus Exp $");
RCSID("$Id: pty.c,v 1.13 2000/04/14 10:30:32 markus Exp $");
#ifdef __FreeBSD__
#include <libutil.h>
#else
#include <util.h>
#endif
#endif /* __FreeBSD__ */
#include "pty.h"
#include "ssh.h"
@ -41,7 +41,7 @@ RCSID("$Id: pty.c,v 1.12 2000/02/15 16:52:58 markus Exp $");
* returned (the buffer must be able to hold at least 64 characters).
*/
int
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
{
#if defined(HAVE_OPENPTY) || defined(BSD4_4)
@ -179,7 +179,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen)
/* Releases the tty. Its ownership is returned to root, and permissions to 0666. */
void
void
pty_release(const char *ttyname)
{
if (chown(ttyname, (uid_t) 0, (gid_t) 0) < 0)
@ -190,7 +190,7 @@ pty_release(const char *ttyname)
/* Makes the tty the processes controlling tty and sets it to sane modes. */
void
void
pty_make_controlling_tty(int *ttyfd, const char *ttyname)
{
int fd;
@ -243,7 +243,7 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname)
/* Changes the window size associated with the pty. */
void
void
pty_change_window_size(int ptyfd, int row, int col,
int xpixel, int ypixel)
{

View File

@ -1,26 +1,28 @@
/*
*
*
* readconf.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Sat Apr 22 00:03:10 1995 ylo
*
*
* Functions for reading the configuration files.
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: readconf.c,v 1.23 2000/02/28 19:51:58 markus Exp $");
RCSID("$Id: readconf.c,v 1.31 2000/05/08 17:12:15 markus Exp $");
#include "ssh.h"
#include "cipher.h"
#include "readconf.h"
#include "match.h"
#include "xmalloc.h"
#include "compat.h"
/* Format of the configuration file:
@ -106,7 +108,8 @@ typedef enum {
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts, oTISAuthentication,
oUsePrivilegedPort, oLogLevel
oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oIdentityFile2,
oGlobalKnownHostsFile2, oUserKnownHostsFile2, oDSAAuthentication
} OpCodes;
/* Textual representations of the tokens. */
@ -122,6 +125,7 @@ static struct {
{ "rhostsauthentication", oRhostsAuthentication },
{ "passwordauthentication", oPasswordAuthentication },
{ "rsaauthentication", oRSAAuthentication },
{ "dsaauthentication", oDSAAuthentication },
{ "skeyauthentication", oSkeyAuthentication },
#ifdef KRB4
{ "kerberos4authentication", oKrb4Authentication },
@ -137,10 +141,13 @@ static struct {
{ "fallbacktorsh", oFallBackToRsh },
{ "usersh", oUseRsh },
{ "identityfile", oIdentityFile },
{ "identityfile2", oIdentityFile2 },
{ "hostname", oHostName },
{ "proxycommand", oProxyCommand },
{ "port", oPort },
{ "cipher", oCipher },
{ "ciphers", oCiphers },
{ "protocol", oProtocol },
{ "remoteforward", oRemoteForward },
{ "localforward", oLocalForward },
{ "user", oUser },
@ -149,6 +156,8 @@ static struct {
{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
{ "globalknownhostsfile", oGlobalKnownHostsFile },
{ "userknownhostsfile", oUserKnownHostsFile },
{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },
{ "userknownhostsfile2", oUserKnownHostsFile2 },
{ "connectionattempts", oConnectionAttempts },
{ "batchmode", oBatchMode },
{ "checkhostip", oCheckHostIP },
@ -171,7 +180,7 @@ static struct {
* error.
*/
void
void
add_local_forward(Options *options, u_short port, const char *host,
u_short host_port)
{
@ -192,7 +201,7 @@ add_local_forward(Options *options, u_short port, const char *host,
* an error.
*/
void
void
add_remote_forward(Options *options, u_short port, const char *host,
u_short host_port)
{
@ -211,7 +220,7 @@ add_remote_forward(Options *options, u_short port, const char *host,
* returns if the token is not known.
*/
static OpCodes
static OpCodes
parse_token(const char *cp, const char *filename, int linenum)
{
unsigned int i;
@ -290,6 +299,10 @@ process_config_line(Options *options, const char *host,
intptr = &options->password_authentication;
goto parse_flag;
case oDSAAuthentication:
intptr = &options->dsa_authentication;
goto parse_flag;
case oRSAAuthentication:
intptr = &options->rsa_authentication;
goto parse_flag;
@ -382,14 +395,22 @@ process_config_line(Options *options, const char *host,
goto parse_int;
case oIdentityFile:
case oIdentityFile2:
cp = strtok(NULL, WHITESPACE);
if (!cp)
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (*activep) {
if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
intptr = (opcode == oIdentityFile) ?
&options->num_identity_files :
&options->num_identity_files2;
if (*intptr >= SSH_MAX_IDENTITY_FILES)
fatal("%.200s line %d: Too many identity files specified (max %d).",
filename, linenum, SSH_MAX_IDENTITY_FILES);
options->identity_files[options->num_identity_files++] = xstrdup(cp);
charptr = (opcode == oIdentityFile) ?
&options->identity_files[*intptr] :
&options->identity_files2[*intptr];
*charptr = xstrdup(cp);
*intptr = *intptr + 1;
}
break;
@ -411,6 +432,14 @@ process_config_line(Options *options, const char *host,
charptr = &options->user_hostfile;
goto parse_string;
case oGlobalKnownHostsFile2:
charptr = &options->system_hostfile2;
goto parse_string;
case oUserKnownHostsFile2:
charptr = &options->user_hostfile2;
goto parse_string;
case oHostName:
charptr = &options->hostname;
goto parse_string;
@ -461,6 +490,26 @@ process_config_line(Options *options, const char *host,
*intptr = value;
break;
case oCiphers:
cp = strtok(NULL, WHITESPACE);
if (!ciphers_valid(cp))
fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, cp ? cp : "<NONE>");
if (*activep && options->ciphers == NULL)
options->ciphers = xstrdup(cp);
break;
case oProtocol:
intptr = &options->protocol;
cp = strtok(NULL, WHITESPACE);
value = proto_spec(cp);
if (value == SSH_PROTO_UNKNOWN)
fatal("%.200s line %d: Bad protocol spec '%s'.",
filename, linenum, cp ? cp : "<NONE>");
if (*activep && *intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
case oLogLevel:
intptr = (int *) &options->log_level;
cp = strtok(NULL, WHITESPACE);
@ -561,7 +610,7 @@ process_config_line(Options *options, const char *host,
* there is an error. If the file does not exist, this returns immediately.
*/
void
void
read_config_file(const char *filename, const char *host, Options *options)
{
FILE *f;
@ -601,7 +650,7 @@ read_config_file(const char *filename, const char *host, Options *options)
* system config file. Last, fill_default_options is called.
*/
void
void
initialize_options(Options * options)
{
memset(options, 'X', sizeof(*options));
@ -611,6 +660,7 @@ initialize_options(Options * options)
options->use_privileged_port = -1;
options->rhosts_authentication = -1;
options->rsa_authentication = -1;
options->dsa_authentication = -1;
options->skey_authentication = -1;
#ifdef KRB4
options->krb4_authentication = -1;
@ -637,13 +687,18 @@ initialize_options(Options * options)
options->connection_attempts = -1;
options->number_of_password_prompts = -1;
options->cipher = -1;
options->ciphers = NULL;
options->protocol = SSH_PROTO_UNKNOWN;
options->num_identity_files = 0;
options->num_identity_files2 = 0;
options->hostname = NULL;
options->proxy_command = NULL;
options->user = NULL;
options->escape_char = -1;
options->system_hostfile = NULL;
options->user_hostfile = NULL;
options->system_hostfile2 = NULL;
options->user_hostfile2 = NULL;
options->num_local_forwards = 0;
options->num_remote_forwards = 0;
options->log_level = (LogLevel) - 1;
@ -654,7 +709,7 @@ initialize_options(Options * options)
* options for which no value has been specified with their default values.
*/
void
void
fill_default_options(Options * options)
{
if (options->forward_agent == -1)
@ -669,6 +724,8 @@ fill_default_options(Options * options)
options->rhosts_authentication = 1;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->dsa_authentication == -1)
options->dsa_authentication = 1;
if (options->skey_authentication == -1)
options->skey_authentication = 0;
#ifdef KRB4
@ -716,18 +773,31 @@ fill_default_options(Options * options)
/* Selected in ssh_login(). */
if (options->cipher == -1)
options->cipher = SSH_CIPHER_NOT_SET;
/* options->ciphers, default set in myproposals.h */
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_1|SSH_PROTO_2|SSH_PROTO_1_PREFERRED;
if (options->num_identity_files == 0) {
options->identity_files[0] =
xmalloc(2 + strlen(SSH_CLIENT_IDENTITY) + 1);
sprintf(options->identity_files[0], "~/%.100s", SSH_CLIENT_IDENTITY);
options->num_identity_files = 1;
}
if (options->num_identity_files2 == 0) {
options->identity_files2[0] =
xmalloc(2 + strlen(SSH_CLIENT_ID_DSA) + 1);
sprintf(options->identity_files2[0], "~/%.100s", SSH_CLIENT_ID_DSA);
options->num_identity_files2 = 1;
}
if (options->escape_char == -1)
options->escape_char = '~';
if (options->system_hostfile == NULL)
options->system_hostfile = SSH_SYSTEM_HOSTFILE;
if (options->user_hostfile == NULL)
options->user_hostfile = SSH_USER_HOSTFILE;
if (options->system_hostfile2 == NULL)
options->system_hostfile2 = SSH_SYSTEM_HOSTFILE2;
if (options->user_hostfile2 == NULL)
options->user_hostfile2 = SSH_USER_HOSTFILE2;
if (options->log_level == (LogLevel) - 1)
options->log_level = SYSLOG_LEVEL_INFO;
/* options->proxy_command should not be set by default */

View File

@ -1,20 +1,20 @@
/*
*
*
* readconf.h
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Sat Apr 22 00:25:29 1995 ylo
*
*
* Functions for reading the configuration file.
*
*
* $FreeBSD$
*/
/* RCSID("$Id: readconf.h,v 1.13 1999/12/01 13:59:15 markus Exp $"); */
/* RCSID("$Id: readconf.h,v 1.18 2000/05/08 17:12:15 markus Exp $"); */
#ifndef READCONF_H
#define READCONF_H
@ -37,6 +37,7 @@ typedef struct {
int rhosts_rsa_authentication; /* Try rhosts with RSA
* authentication. */
int rsa_authentication; /* Try RSA authentication. */
int dsa_authentication; /* Try DSA authentication. */
int skey_authentication; /* Try S/Key or TIS authentication. */
#ifdef KRB4
int krb4_authentication; /* Try Kerberos v4
@ -71,6 +72,8 @@ typedef struct {
int number_of_password_prompts; /* Max number of password
* prompts. */
int cipher; /* Cipher to use. */
char *ciphers; /* SSH2 ciphers in order of preference. */
int protocol; /* Protocol in order of preference. */
char *hostname; /* Real host to connect. */
char *proxy_command; /* Proxy command for connecting the host. */
char *user; /* User to log in as. */
@ -78,9 +81,13 @@ typedef struct {
char *system_hostfile;/* Path for /etc/ssh_known_hosts. */
char *user_hostfile; /* Path for $HOME/.ssh/known_hosts. */
char *system_hostfile2;
char *user_hostfile2;
int num_identity_files; /* Number of files for RSA identities. */
int num_identity_files2; /* DSA identities. */
char *identity_files[SSH_MAX_IDENTITY_FILES];
char *identity_files2[SSH_MAX_IDENTITY_FILES];
/* Local TCP/IP forward requests. */
int num_local_forwards;
@ -111,7 +118,7 @@ void fill_default_options(Options * options);
* only sets those values that have not already been set. Returns 0 for legal
* options
*/
int
int
process_config_line(Options * options, const char *host,
char *line, const char *filename, int linenum,
int *activep);
@ -121,7 +128,7 @@ process_config_line(Options * options, const char *host,
* should already be initialized before this call. This never returns if
* there is an error. If the file does not exist, this returns immediately.
*/
void
void
read_config_file(const char *filename, const char *host,
Options * options);
@ -129,7 +136,7 @@ read_config_file(const char *filename, const char *host,
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
*/
void
void
add_local_forward(Options * options, u_short port, const char *host,
u_short host_port);
@ -137,7 +144,7 @@ add_local_forward(Options * options, u_short port, const char *host,
* Adds a remote TCP/IP port forward to options. Never returns if there is
* an error.
*/
void
void
add_remote_forward(Options * options, u_short port, const char *host,
u_short host_port);

View File

@ -1,43 +1,42 @@
/*
*
*
* rsa.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Fri Mar 3 22:07:06 1995 ylo
*
*
* Description of the RSA algorithm can be found e.g. from the following sources:
*
*
* Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1994.
*
*
* Jennifer Seberry and Josed Pieprzyk: Cryptography: An Introduction to
* Computer Security. Prentice-Hall, 1989.
*
*
* Man Young Rhee: Cryptography and Secure Data Communications. McGraw-Hill,
* 1994.
*
*
* R. Rivest, A. Shamir, and L. M. Adleman: Cryptographic Communications
* System and Method. US Patent 4,405,829, 1983.
*
*
* Hans Riesel: Prime Numbers and Computer Methods for Factorization.
* Birkhauser, 1994.
*
*
* The RSA Frequently Asked Questions document by RSA Data Security, Inc., 1995.
*
*
* RSA in 3 lines of perl by Adam Back <aba@atlax.ex.ac.uk>, 1995, as included
* below:
*
*
* [gone - had to be deleted - what a pity]
*
* $FreeBSD$
*
*/
#include "includes.h"
RCSID("$Id: rsa.c,v 1.13 2000/03/16 20:56:14 markus Exp $");
RCSID("$Id: rsa.c,v 1.14 2000/04/14 10:30:32 markus Exp $");
#include "rsa.h"
#include "ssh.h"

View File

@ -1,20 +1,20 @@
/*
*
*
* rsa.h
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Fri Mar 3 22:01:06 1995 ylo
*
*
* RSA key generation, encryption and decryption.
*
*
* $FreeBSD$
*/
/* RCSID("$Id: rsa.h,v 1.4 1999/11/24 19:53:50 markus Exp $"); */
/* RCSID("$Id: rsa.h,v 1.6 2000/04/14 10:30:32 markus Exp $"); */
#ifndef RSA_H
#define RSA_H

View File

@ -1,30 +1,31 @@
/*
*
*
* servconf.c
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Mon Aug 21 15:48:58 1995 ylo
*
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$Id: servconf.c,v 1.31 2000/03/07 20:40:41 markus Exp $");
RCSID("$Id: servconf.c,v 1.40 2000/05/08 17:12:15 markus Exp $");
#include "ssh.h"
#include "servconf.h"
#include "xmalloc.h"
#include "compat.h"
/* add listen address */
void add_listen_addr(ServerOptions *options, char *addr);
/* Initializes the server options to their default values. */
void
void
initialize_server_options(ServerOptions *options)
{
memset(options, 0, sizeof(*options));
@ -32,6 +33,8 @@ initialize_server_options(ServerOptions *options)
options->ports_from_cmdline = 0;
options->listen_addrs = NULL;
options->host_key_file = NULL;
options->host_dsa_key_file = NULL;
options->pid_file = NULL;
options->server_key_bits = -1;
options->login_grace_time = -1;
options->key_regeneration_time = -1;
@ -49,6 +52,7 @@ initialize_server_options(ServerOptions *options)
options->rhosts_authentication = -1;
options->rhosts_rsa_authentication = -1;
options->rsa_authentication = -1;
options->dsa_authentication = -1;
#ifdef KRB4
options->krb4_authentication = -1;
options->krb4_or_local_passwd = -1;
@ -72,11 +76,14 @@ initialize_server_options(ServerOptions *options)
options->num_deny_users = 0;
options->num_allow_groups = 0;
options->num_deny_groups = 0;
options->ciphers = NULL;
options->protocol = SSH_PROTO_UNKNOWN;
options->gateway_ports = -1;
options->connections_per_period = 0;
options->connections_period = 0;
}
void
void
fill_default_server_options(ServerOptions *options)
{
if (options->num_ports == 0)
@ -85,6 +92,10 @@ fill_default_server_options(ServerOptions *options)
add_listen_addr(options, NULL);
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)
options->pid_file = SSH_DAEMON_PID_FILE;
if (options->server_key_bits == -1)
options->server_key_bits = 768;
if (options->login_grace_time == -1)
@ -119,6 +130,8 @@ fill_default_server_options(ServerOptions *options)
options->rhosts_rsa_authentication = 0;
if (options->rsa_authentication == -1)
options->rsa_authentication = 1;
if (options->dsa_authentication == -1)
options->dsa_authentication = 1;
#ifdef KRB4
if (options->krb4_authentication == -1)
options->krb4_authentication = (access(KEYFILE, R_OK) == 0);
@ -149,6 +162,10 @@ fill_default_server_options(ServerOptions *options)
options->permit_empty_passwd = 0;
if (options->use_login == -1)
options->use_login = 0;
if (options->protocol == SSH_PROTO_UNKNOWN)
options->protocol = SSH_PROTO_1|SSH_PROTO_2;
if (options->gateway_ports == -1)
options->gateway_ports = 0;
}
#define WHITESPACE " \t\r\n"
@ -175,7 +192,8 @@ typedef enum {
sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset,
sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail,
sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
sIgnoreUserKnownHosts, sConnectionsPerPeriod
sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile,
sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod
} ServerOpCodes;
/* Textual representation of the tokens. */
@ -185,6 +203,8 @@ static struct {
} keywords[] = {
{ "port", sPort },
{ "hostkey", sHostKeyFile },
{ "hostdsakey", sHostDSAKeyFile },
{ "pidfile", sPidFile },
{ "serverkeybits", sServerKeyBits },
{ "logingracetime", sLoginGraceTime },
{ "keyregenerationinterval", sKeyRegenerationTime },
@ -194,6 +214,7 @@ static struct {
{ "rhostsauthentication", sRhostsAuthentication },
{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
{ "rsaauthentication", sRSAAuthentication },
{ "dsaauthentication", sDSAAuthentication },
#ifdef KRB4
{ "kerberos4authentication", sKrb4Authentication },
{ "kerberos4orlocalpasswd", sKrb4OrLocalPasswd },
@ -227,6 +248,9 @@ static struct {
{ "denyusers", sDenyUsers },
{ "allowgroups", sAllowGroups },
{ "denygroups", sDenyGroups },
{ "ciphers", sCiphers },
{ "protocol", sProtocol },
{ "gatewayports", sGatewayPorts },
{ "connectionsperperiod", sConnectionsPerPeriod },
{ NULL, 0 }
};
@ -236,7 +260,7 @@ static struct {
* returns if the token is not known.
*/
static ServerOpCodes
static ServerOpCodes
parse_token(const char *cp, const char *filename,
int linenum)
{
@ -254,7 +278,7 @@ parse_token(const char *cp, const char *filename,
/*
* add listen address
*/
void
void
add_listen_addr(ServerOptions *options, char *addr)
{
extern int IPv4or6;
@ -284,7 +308,7 @@ add_listen_addr(ServerOptions *options, char *addr)
/* Reads the server configuration file. */
void
void
read_server_config(ServerOptions *options, const char *filename)
{
FILE *f;
@ -320,7 +344,7 @@ read_server_config(ServerOptions *options, const char *filename)
"ListenAdress.\n", filename, linenum);
if (options->num_ports >= MAX_PORTS)
fatal("%s line %d: too many ports.\n",
filename, linenum);
filename, linenum);
cp = strtok(NULL, WHITESPACE);
if (!cp)
fatal("%s line %d: missing port number.\n",
@ -363,11 +387,25 @@ read_server_config(ServerOptions *options, const char *filename)
break;
case sHostKeyFile:
charptr = &options->host_key_file;
case sHostDSAKeyFile:
charptr = (opcode == sHostKeyFile ) ?
&options->host_key_file : &options->host_dsa_key_file;
cp = strtok(NULL, WHITESPACE);
if (!cp) {
fprintf(stderr, "%s line %d: missing file name.\n",
filename, linenum);
filename, linenum);
exit(1);
}
if (*charptr == NULL)
*charptr = tilde_expand_filename(cp, getuid());
break;
case sPidFile:
charptr = &options->pid_file;
cp = strtok(NULL, WHITESPACE);
if (!cp) {
fprintf(stderr, "%s line %d: missing file name.\n",
filename, linenum);
exit(1);
}
if (*charptr == NULL)
@ -441,6 +479,10 @@ read_server_config(ServerOptions *options, const char *filename)
intptr = &options->rsa_authentication;
goto parse_flag;
case sDSAAuthentication:
intptr = &options->dsa_authentication;
goto parse_flag;
#ifdef KRB4
case sKrb4Authentication:
intptr = &options->krb4_authentication;
@ -517,13 +559,17 @@ read_server_config(ServerOptions *options, const char *filename)
intptr = &options->use_login;
goto parse_flag;
case sGatewayPorts:
intptr = &options->gateway_ports;
goto parse_flag;
case sLogFacility:
intptr = (int *) &options->log_facility;
cp = strtok(NULL, WHITESPACE);
value = log_facility_number(cp);
if (value == (SyslogFacility) - 1)
fatal("%.200s line %d: unsupported log facility '%s'\n",
filename, linenum, cp ? cp : "<NONE>");
filename, linenum, cp ? cp : "<NONE>");
if (*intptr == -1)
*intptr = (SyslogFacility) value;
break;
@ -534,7 +580,7 @@ read_server_config(ServerOptions *options, const char *filename)
value = log_level_number(cp);
if (value == (LogLevel) - 1)
fatal("%.200s line %d: unsupported log level '%s'\n",
filename, linenum, cp ? cp : "<NONE>");
filename, linenum, cp ? cp : "<NONE>");
if (*intptr == -1)
*intptr = (LogLevel) value;
break;
@ -542,17 +588,16 @@ read_server_config(ServerOptions *options, const char *filename)
case sAllowUsers:
while ((cp = strtok(NULL, WHITESPACE))) {
if (options->num_allow_users >= MAX_ALLOW_USERS)
fatal("%.200s line %d: too many allow users.\n", filename,
linenum);
fatal("%.200s line %d: too many allow users.\n",
filename, linenum);
options->allow_users[options->num_allow_users++] = xstrdup(cp);
}
break;
case sDenyUsers:
while ((cp = strtok(NULL, WHITESPACE))) {
if (options->num_deny_users >= MAX_DENY_USERS)
fatal("%.200s line %d: too many deny users.\n", filename,
linenum);
fatal("%.200s line %d: too many deny users.\n",
filename, linenum);
options->deny_users[options->num_deny_users++] = xstrdup(cp);
}
break;
@ -560,8 +605,8 @@ read_server_config(ServerOptions *options, const char *filename)
case sAllowGroups:
while ((cp = strtok(NULL, WHITESPACE))) {
if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
fatal("%.200s line %d: too many allow groups.\n", filename,
linenum);
fatal("%.200s line %d: too many allow groups.\n",
filename, linenum);
options->allow_groups[options->num_allow_groups++] = xstrdup(cp);
}
break;
@ -569,12 +614,32 @@ read_server_config(ServerOptions *options, const char *filename)
case sDenyGroups:
while ((cp = strtok(NULL, WHITESPACE))) {
if (options->num_deny_groups >= MAX_DENY_GROUPS)
fatal("%.200s line %d: too many deny groups.\n", filename,
linenum);
fatal("%.200s line %d: too many deny groups.\n",
filename, linenum);
options->deny_groups[options->num_deny_groups++] = xstrdup(cp);
}
break;
case sCiphers:
cp = strtok(NULL, WHITESPACE);
if (!ciphers_valid(cp))
fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
filename, linenum, cp ? cp : "<NONE>");
if (options->ciphers == NULL)
options->ciphers = xstrdup(cp);
break;
case sProtocol:
intptr = &options->protocol;
cp = strtok(NULL, WHITESPACE);
value = proto_spec(cp);
if (value == SSH_PROTO_UNKNOWN)
fatal("%s line %d: Bad protocol spec '%s'.",
filename, linenum, cp ? cp : "<NONE>");
if (*intptr == SSH_PROTO_UNKNOWN)
*intptr = value;
break;
case sConnectionsPerPeriod:
cp = strtok(NULL, WHITESPACE);
if (cp == NULL)
@ -594,12 +659,14 @@ read_server_config(ServerOptions *options, const char *filename)
fatal("%.200s line %d: Missing handler for opcode %s (%d)\n",
filename, linenum, cp, opcode);
}
if (strtok(NULL, WHITESPACE) != NULL)
fatal("%.200s line %d: garbage at end of line.\n", filename,
linenum);
if (strtok(NULL, WHITESPACE) != NULL) {
fatal("%.200s line %d: garbage at end of line.\n",
filename, linenum);
}
}
fclose(f);
if (bad_options > 0)
if (bad_options > 0) {
fatal("%.200s: terminating, %d bad configuration options\n",
filename, bad_options);
}
}

View File

@ -1,20 +1,20 @@
/*
*
*
* servconf.h
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Mon Aug 21 15:35:03 1995 ylo
*
*
* Definitions for server configuration data and for the functions reading it.
*
*
* $FreeBSD$
*/
/* RCSID("$Id: servconf.h,v 1.15 2000/01/04 00:08:00 markus Exp $"); */
/* RCSID("$Id: servconf.h,v 1.22 2000/05/06 17:45:37 markus Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
@ -33,6 +33,8 @@ typedef struct {
char *listen_addr; /* Address 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_dsa_key_file; /* File containing dsa host key. */
char *pid_file; /* Where to put our pid */
int server_key_bits;/* Size of the server key. */
int login_grace_time; /* Disconnect if no auth in this time
* (sec). */
@ -48,6 +50,9 @@ typedef struct {
* searching at */
int strict_modes; /* If true, require string home dir modes. */
int keepalives; /* If true, set SO_KEEPALIVE. */
char *ciphers; /* Ciphers in order of preference. */
int protocol; /* Protocol in order of preference. */
int gateway_ports; /* If true, allow remote connects to forwarded ports. */
SyslogFacility log_facility; /* Facility for system logging. */
LogLevel log_level; /* Level for system logging. */
int rhosts_authentication; /* If true, permit rhosts
@ -55,6 +60,7 @@ typedef struct {
int rhosts_rsa_authentication; /* If true, permit rhosts RSA
* authentication. */
int rsa_authentication; /* If true, permit RSA authentication. */
int dsa_authentication; /* If true, permit DSA authentication. */
#ifdef KRB4
int krb4_authentication; /* If true, permit Kerberos v4
* authentication. */

View File

@ -5,6 +5,8 @@
/*
* SSH2 support by Markus Friedl.
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* $FreeBSD$
*/
#include "includes.h"
@ -27,6 +29,15 @@ RCSID("$OpenBSD: session.c,v 1.12 2000/05/03 18:03:07 markus Exp $");
#include "ssh2.h"
#include "auth.h"
#ifdef __FreeBSD__
#define LOGIN_CAP
#define _PATH_CHPASS "/usr/bin/passwd"
#endif /* __FreeBSD__ */
#ifdef LOGIN_CAP
#include <login_cap.h>
#endif /* LOGIN_CAP */
/* types */
#define TTYSZ 64
@ -504,6 +515,15 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
struct sockaddr_storage from;
struct stat st;
time_t last_login_time;
#ifdef LOGIN_CAP
login_cap_t *lc;
char *fname;
#endif /* LOGIN_CAP */
#ifdef __FreeBSD__
#define DEFAULT_WARN (2L * 7L * 86400L) /* Two weeks */
struct timeval tv;
time_t warntime = DEFAULT_WARN;
#endif /* __FreeBSD__ */
if (s == NULL)
fatal("do_exec_pty: no session");
@ -574,6 +594,66 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir);
quiet_login = stat(line, &st) >= 0;
#ifdef LOGIN_CAP
lc = login_getpwclass(pw);
if (lc == NULL)
lc = login_getclassbyname(NULL, pw);
quiet_login = login_getcapbool(lc, "hushlogin", quiet_login);
#endif /* LOGIN_CAP */
#ifdef __FreeBSD__
if (pw->pw_change || pw->pw_expire)
(void)gettimeofday(&tv, NULL);
#ifdef LOGIN_CAP
warntime = login_getcaptime(lc, "warnpassword",
DEFAULT_WARN, DEFAULT_WARN);
#endif /* LOGIN_CAP */
/*
* If the password change time is set and has passed, give the
* user a password expiry notice and chance to change it.
*/
if (pw->pw_change != 0) {
if (tv.tv_sec >= pw->pw_change) {
(void)printf(
"Sorry -- your password has expired.\n");
log("%s Password expired - forcing change",
pw->pw_name);
command = _PATH_CHPASS;
} else if (pw->pw_change - tv.tv_sec < warntime &&
!quiet_login)
(void)printf(
"Warning: your password expires on %s",
ctime(&pw->pw_change));
}
#ifdef LOGIN_CAP
warntime = login_getcaptime(lc, "warnexpire",
DEFAULT_WARN, DEFAULT_WARN);
#endif /* LOGIN_CAP */
if (pw->pw_expire) {
if (tv.tv_sec >= pw->pw_expire) {
(void)printf(
"Sorry -- your account has expired.\n");
log(
"LOGIN %.200s REFUSED (EXPIRED) FROM %.200s ON TTY %.200s",
pw->pw_name, hostname, ttyname);
exit(254);
} else if (pw->pw_expire - tv.tv_sec < warntime &&
!quiet_login)
(void)printf(
"Warning: your account expires on %s",
ctime(&pw->pw_expire));
}
#endif /* __FreeBSD__ */
#ifdef LOGIN_CAP
if (!auth_ttyok(lc, ttyname)) {
(void)printf("Permission denied.\n");
log(
"LOGIN %.200s REFUSED (TTY) FROM %.200s ON TTY %.200s",
pw->pw_name, hostname, ttyname);
exit(254);
}
#endif /* LOGIN_CAP */
/*
* If the user has logged in before, display the time of last
* login. However, don't display anything extra if a command
@ -596,6 +676,22 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
else
printf("Last login: %s from %s\r\n", time_string, buf);
}
#ifdef LOGIN_CAP
if (command == NULL && !quiet_login && !options.use_login) {
fname = login_getcapstr(lc, "copyright", NULL, NULL);
if (fname != NULL && (f = fopen(fname, "r")) != NULL) {
while (fgets(line, sizeof(line), f) != NULL)
fputs(line, stdout);
fclose(f);
} else
(void)printf("%s\n\t%s %s\n",
"Copyright (c) 1980, 1983, 1986, 1988, 1990, 1991, 1993, 1994",
"The Regents of the University of California. ",
"All rights reserved.");
}
#endif /* LOGIN_CAP */
/*
* Print /etc/motd unless a command was specified or printing
* it was disabled in server options or login(1) will be
@ -604,14 +700,24 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw)
*/
if (command == NULL && options.print_motd && !quiet_login &&
!options.use_login) {
/* Print /etc/motd if it exists. */
#ifdef LOGIN_CAP
fname = login_getcapstr(lc, "welcome", NULL, NULL);
if (fname == NULL || (f = fopen(fname, "r")) == NULL)
f = fopen("/etc/motd", "r");
#else /* !LOGIN_CAP */
f = fopen("/etc/motd", "r");
#endif /* LOGIN_CAP */
/* Print /etc/motd if it exists. */
if (f) {
while (fgets(line, sizeof(line), f))
fputs(line, stdout);
fclose(f);
}
}
#ifdef LOGIN_CAP
login_close(lc);
#endif /* LOGIN_CAP */
/* Do common processing for the child, such as execing the command. */
do_child(command, pw, s->term, s->display, s->auth_proto, s->auth_data, s->tty);
/* NOTREACHED */
@ -735,15 +841,25 @@ do_child(const char *command, struct passwd * pw, const char *term,
const char *display, const char *auth_proto,
const char *auth_data, const char *ttyname)
{
const char *shell, *cp = NULL;
char *shell;
const char *cp = NULL;
char buf[256];
FILE *f;
unsigned int envsize, i;
char **env;
char **env = NULL;
extern char **environ;
struct stat st;
char *argv[10];
#ifdef LOGIN_CAP
login_cap_t *lc;
lc = login_getpwclass(pw);
if (lc == NULL)
lc = login_getclassbyname(NULL, pw);
if (pw->pw_uid != 0)
auth_checknologin(lc);
#else /* !LOGIN_CAP */
f = fopen("/etc/nologin", "r");
if (f) {
/* /etc/nologin exists. Print its contents and exit. */
@ -753,6 +869,11 @@ do_child(const char *command, struct passwd * pw, const char *term,
if (pw->pw_uid != 0)
exit(254);
}
#endif /* LOGIN_CAP */
#ifdef LOGIN_CAP
if (options.use_login)
#endif /* LOGIN_CAP */
/* Set login name in the kernel. */
if (setlogin(pw->pw_name) < 0)
error("setlogin failed: %s", strerror(errno));
@ -761,6 +882,42 @@ do_child(const char *command, struct passwd * pw, const char *term,
/* Login(1) does this as well, and it needs uid 0 for the "-h"
switch, so we let login(1) to this for us. */
if (!options.use_login) {
#ifdef LOGIN_CAP
char **tmpenv;
/* Initialize temp environment */
envsize = 64;
env = xmalloc(envsize * sizeof(char *));
env[0] = NULL;
child_set_env(&env, &envsize, "PATH",
(pw->pw_uid == 0) ?
_PATH_STDPATH : _PATH_DEFPATH);
snprintf(buf, sizeof buf, "%.200s/%.50s",
_PATH_MAILDIR, pw->pw_name);
child_set_env(&env, &envsize, "MAIL", buf);
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
/* Save parent environment */
tmpenv = environ;
environ = env;
if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETALL) < 0)
fatal("setusercontext failed: %s", strerror(errno));
/* Restore parent environment */
env = environ;
environ = tmpenv;
for (envsize = 0; env[envsize] != NULL; ++envsize)
;
envsize = (envsize < 100) ? 100 : envsize + 16;
env = xrealloc(env, envsize * sizeof(char *));
#else /* !LOGIN_CAP */
if (getuid() == 0 || geteuid() == 0) {
if (setgid(pw->pw_gid) < 0) {
perror("setgid");
@ -778,12 +935,16 @@ do_child(const char *command, struct passwd * pw, const char *term,
}
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %d.", (int) pw->pw_uid);
#endif /* LOGIN_CAP */
}
/*
* Get the shell from the password data. An empty shell field is
* legal, and means /bin/sh.
*/
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
#ifdef LOGIN_CAP
shell = login_getcapstr(lc, "shell", shell, shell);
#endif /* LOGIN_CAP */
#ifdef AFS
/* Try to get AFS tokens for the local cell. */
@ -798,24 +959,31 @@ do_child(const char *command, struct passwd * pw, const char *term,
#endif /* AFS */
/* Initialize the environment. */
envsize = 100;
env = xmalloc(envsize * sizeof(char *));
env[0] = NULL;
if (env == NULL) {
envsize = 100;
env = xmalloc(envsize * sizeof(char *));
env[0] = NULL;
}
if (!options.use_login) {
/* Set basic environment. */
child_set_env(&env, &envsize, "USER", pw->pw_name);
child_set_env(&env, &envsize, "LOGNAME", pw->pw_name);
child_set_env(&env, &envsize, "HOME", pw->pw_dir);
#ifndef LOGIN_CAP
child_set_env(&env, &envsize, "PATH", _PATH_STDPATH);
snprintf(buf, sizeof buf, "%.200s/%.50s",
_PATH_MAILDIR, pw->pw_name);
child_set_env(&env, &envsize, "MAIL", buf);
#endif /* !LOGIN_CAP */
/* Normal systems set SHELL by default. */
child_set_env(&env, &envsize, "SHELL", shell);
}
#ifdef LOGIN_CAP
if (options.use_login)
#endif /* LOGIN_CAP */
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
@ -853,6 +1021,31 @@ do_child(const char *command, struct passwd * pw, const char *term,
child_set_env(&env, &envsize, "KRBTKFILE", ticket);
}
#endif /* KRB4 */
#ifdef KRB5
{
extern krb5_ccache mem_ccache;
if (mem_ccache) {
krb5_error_code problem;
krb5_ccache ccache;
#ifdef AFS
if (k_hasafs())
krb5_afslog(ssh_context, mem_ccache, NULL, NULL);
#endif /* AFS */
problem = krb5_cc_default(ssh_context, &ccache);
if (problem) {}
else {
problem = krb5_cc_copy_cache(ssh_context, mem_ccache, ccache);
if (problem) {}
}
krb5_cc_close(ssh_context, ccache);
}
krb5_cleanup_proc(NULL);
}
#endif /* KRB5 */
if (xauthfile)
child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
@ -903,13 +1096,50 @@ do_child(const char *command, struct passwd * pw, const char *term,
* initgroups, because at least on Solaris 2.3 it leaves file
* descriptors open.
*/
for (i = 3; i < 64; i++)
for (i = 3; i < getdtablesize(); i++)
close(i);
/* Change current directory to the user\'s home directory. */
if (chdir(pw->pw_dir) < 0)
if (
#ifdef __FreeBSD__
!*pw->pw_dir ||
#endif /* __FreeBSD__ */
chdir(pw->pw_dir) < 0
) {
#ifdef __FreeBSD__
int quiet_login = 0;
#endif /* __FreeBSD__ */
#ifdef LOGIN_CAP
if (login_getcapbool(lc, "requirehome", 0)) {
(void)printf("Home directory not available\n");
log("LOGIN %.200s REFUSED (HOMEDIR) ON TTY %.200s",
pw->pw_name, ttyname);
exit(254);
}
#endif /* LOGIN_CAP */
#ifdef __FreeBSD__
if (chdir("/") < 0) {
(void)printf("Cannot find root directory\n");
log("LOGIN %.200s REFUSED (ROOTDIR) ON TTY %.200s",
pw->pw_name, ttyname);
exit(254);
}
#ifdef LOGIN_CAP
quiet_login = login_getcapbool(lc, "hushlogin", 0);
#endif /* LOGIN_CAP */
if (!quiet_login || *pw->pw_dir)
(void)printf(
"No home directory.\nLogging in with home = \"/\".\n");
#else /* !__FreeBSD__ */
fprintf(stderr, "Could not chdir to home directory %s: %s\n",
pw->pw_dir, strerror(errno));
#endif /* __FreeBSD__ */
}
#ifdef LOGIN_CAP
login_close(lc);
#endif /* LOGIN_CAP */
/*
* Must take new environment into use so that .ssh/rc, /etc/sshrc and
@ -989,7 +1219,11 @@ do_child(const char *command, struct passwd * pw, const char *term,
mailbox = getenv("MAIL");
if (mailbox != NULL) {
if (stat(mailbox, &mailstat) != 0 || mailstat.st_size == 0)
#ifdef __FreeBSD__
;
#else /* !__FreeBSD__ */
printf("No mail.\n");
#endif /* __FreeBSD__ */
else if (mailstat.st_mtime < mailstat.st_atime)
printf("You have mail.\n");
else

View File

@ -1,4 +1,5 @@
/* $OpenBSD: ssh-agent.c,v 1.26 2000/03/16 20:56:14 markus Exp $ */
/* $FreeBSD$ */
/* $OpenBSD: ssh-agent.c,v 1.31 2000/04/29 18:11:52 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -6,12 +7,10 @@
* All rights reserved
* Created: Wed Mar 29 03:46:59 1995 ylo
* The authentication agent program.
*
* $FreeBSD$
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-agent.c,v 1.26 2000/03/16 20:56:14 markus Exp $");
RCSID("$OpenBSD: ssh-agent.c,v 1.31 2000/04/29 18:11:52 markus Exp $");
#include "ssh.h"
#include "rsa.h"
@ -48,7 +47,7 @@ Identity *identities = NULL;
int max_fd = 0;
/* pid of shell == parent of agent */
int parent_pid = -1;
pid_t parent_pid = -1;
/* pathname and directory for AUTH_SOCKET */
char socket_name[1024];
@ -176,7 +175,7 @@ process_remove_identity(SocketEntry *e)
buffer_get_bignum(&e->input, n);
if (bits != BN_num_bits(n))
error("Warning: identity keysize mismatch: actual %d, announced %d",
log("Warning: identity keysize mismatch: actual %d, announced %d",
BN_num_bits(n), bits);
/* Check if we have the key. */
@ -405,7 +404,7 @@ prepare_select(fd_set *readset, fd_set *writeset)
}
}
void
void
after_select(fd_set *readset, fd_set *writeset)
{
unsigned int i;
@ -438,6 +437,8 @@ after_select(fd_set *readset, fd_set *writeset)
shutdown(sockets[i].fd, SHUT_RDWR);
close(sockets[i].fd);
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
break;
}
buffer_consume(&sockets[i].output, len);
@ -448,6 +449,8 @@ after_select(fd_set *readset, fd_set *writeset)
shutdown(sockets[i].fd, SHUT_RDWR);
close(sockets[i].fd);
sockets[i].type = AUTH_UNUSED;
buffer_free(&sockets[i].input);
buffer_free(&sockets[i].output);
break;
}
buffer_append(&sockets[i].input, buf, len);
@ -462,7 +465,7 @@ after_select(fd_set *readset, fd_set *writeset)
void
check_parent_exists(int sig)
{
if (kill(parent_pid, 0) < 0) {
if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
/* printf("Parent has died - Authentication agent exiting.\n"); */
exit(1);
}
@ -548,6 +551,7 @@ main(int ac, char **av)
}
pid = atoi(pidstr);
if (pid < 1) { /* XXX PID_MAX check too */
/* Yes, PID_MAX check please */
fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
SSH_AGENTPID_ENV_NAME, pidstr);
exit(1);
@ -639,8 +643,8 @@ main(int ac, char **av)
}
signal(SIGINT, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGHUP, cleanup_exit);
signal(SIGTERM, cleanup_exit);
signal(SIGHUP, cleanup_exit);
signal(SIGTERM, cleanup_exit);
while (1) {
FD_ZERO(&readset);
FD_ZERO(&writeset);

View File

@ -10,6 +10,7 @@
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\"
.\" $Id: ssh.1,v 1.43 2000/03/24 03:04:46 brad Exp $
.\" $Id: ssh.1,v 1.52 2000/05/08 17:21:32 hugh Exp $
.\" $FreeBSD$
.\"
.Dd September 25, 1999
@ -25,8 +26,8 @@
.Op Ar command
.Pp
.Nm ssh
.Op Fl afgknqtvxCPX46
.Op Fl c Ar blowfish | 3des
.Op Fl afgknqtvxCPX246
.Op Fl c Ar cipher_spec
.Op Fl e Ar escape_char
.Op Fl i Ar identity_file
.Op Fl l Ar login_name
@ -64,7 +65,10 @@ arbitrary TCP/IP ports can also be forwarded over the secure channel.
connects and logs into the specified
.Ar hostname .
The user must prove
his/her identity to the remote machine using one of several methods.
his/her identity to the remote machine using one of several methods
depending on the protocol version used:
.Pp
.Ss SSH protocol version 1
.Pp
First, if the machine the user logs in from is listed in
.Pa /etc/hosts.equiv
@ -89,8 +93,8 @@ or
.Pa hosts.equiv
method combined with RSA-based host authentication.
It means that if the login would be permitted by
.Pa \&.rhosts ,
.Pa \&.shosts ,
.Pa $HOME/.rhosts ,
.Pa $HOME/.shosts ,
.Pa /etc/hosts.equiv ,
or
.Pa /etc/ssh/shosts.equiv ,
@ -106,7 +110,7 @@ This authentication method closes security holes due to IP
spoofing, DNS spoofing and routing spoofing.
[Note to the administrator:
.Pa /etc/hosts.equiv ,
.Pa \&.rhosts ,
.Pa $HOME/.rhosts ,
and the rlogin/rsh protocol in general, are inherently insecure and should be
disabled if security is desired.]
.Pp
@ -117,10 +121,10 @@ The scheme is based on public-key cryptography: there are cryptosystems
where encryption and decryption are done using separate keys, and it
is not possible to derive the decryption key from the encryption key.
RSA is one such system.
The idea is that each user creates a public/private
The idea is that each user creates a public/private
key pair for authentication purposes.
The server knows the public key, and only the user knows the private key.
The file
The file
.Pa $HOME/.ssh/authorized_keys
lists the public keys that are permitted for logging
in.
@ -144,18 +148,18 @@ implements the RSA authentication protocol automatically.
The user creates his/her RSA key pair by running
.Xr ssh-keygen 1 .
This stores the private key in
.Pa \&.ssh/identity
.Pa $HOME/.ssh/identity
and the public key in
.Pa \&.ssh/identity.pub
.Pa $HOME/.ssh/identity.pub
in the user's home directory.
The user should then copy the
.Pa identity.pub
to
.Pa \&.ssh/authorized_keys
.Pa $HOME/.ssh/authorized_keys
in his/her home directory on the remote machine (the
.Pa authorized_keys
file corresponds to the conventional
.Pa \&.rhosts
.Pa $HOME/.rhosts
file, and has one key
per line, though the lines can be very long).
After this, the user can log in without giving the password.
@ -175,6 +179,38 @@ The password is sent to the remote
host for checking; however, since all communications are encrypted,
the password cannot be seen by someone listening on the network.
.Pp
.Ss SSH protocol version 2
.Pp
When a user connects using the protocol version 2
different authentication methods are available:
At first, the client attempts to authenticate using the public key method.
If this method fails password authentication is tried.
.Pp
The public key method is similar to RSA authentication described
in the previous section except that the DSA algorithm is used
instead of the patented RSA algorithm.
The client uses his private DSA key
.Pa $HOME/.ssh/id_dsa
to sign the session identifier and sends the result to the server.
The server checks whether the matching public key is listed in
.Pa $HOME/.ssh/authorized_keys2
and grants access if both the key is found and the signature is correct.
The session identifier is derived from a shared Diffie-Hellman value
and is only known to the client and the server.
.Pp
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.
This protocol 2 implementation does not yet support Kerberos or
S/Key authentication.
.Pp
Protocol 2 provides additional mechanisms for confidentiality
(the traffic is encrypted using 3DES, Blowfish, CAST128 or Arcfour)
and integrity (hmac-sha1, hmac-md5).
Note that protocol 1 lacks a strong mechanism for ensuring the
integrity of the connection.
.Pp
.Ss Login session and remote execution
.Pp
When the user's identity has been accepted by the server, the server
either executes the given command, or logs into the machine and gives
the user a normal shell on the remote machine.
@ -220,6 +256,8 @@ The exit status of the remote program is returned as the exit status
of
.Nm ssh .
.Pp
.Ss X11 and TCP forwarding
.Pp
If the user is using X11 (the
.Ev DISPLAY
environment variable is set), the connection to the X11 display can
@ -264,15 +302,22 @@ be specified either on command line or in a configuration file.
One possible application of TCP/IP forwarding is a secure connection to an
electronic purse; another is going trough firewalls.
.Pp
.Ss Server authentication
.Pp
.Nm
automatically maintains and checks a database containing RSA-based
automatically maintains and checks a database containing
identifications for all hosts it has ever been used with.
The database is stored in
.Pa \&.ssh/known_hosts
RSA host keys are stored in
.Pa $HOME/.ssh/known_hosts
and
DSA host keys are stored in
.Pa $HOME/.ssh/known_hosts2
in the user's home directory.
Additionally, the file
Additionally, the files
.Pa /etc/ssh/ssh_known_hosts
is automatically checked for known hosts.
and
.Pa /etc/ssh/ssh_known_hosts2
are automatically checked for known hosts.
Any new hosts are automatically added to the user's file.
If a host's identification
ever changes,
@ -295,15 +340,20 @@ This may also be specified on a per-host basis in the configuration file.
Selects the cipher to use for encrypting the session.
.Ar 3des
is used by default.
It is believed to be secure.
It is believed to be secure.
.Ar 3des
(triple-des) is an encrypt-decrypt-encrypt triple with three different keys.
It is presumably more secure than the
.Ar des
cipher which is no longer supported in ssh.
cipher which is no longer supported in
.Nm ssh .
.Ar blowfish
is a fast block cipher, it appears very secure and is much faster than
.Ar 3des .
.It Fl c Ar "3des-cbc,blowfish-cbc,arcfour,cast128-cbc"
Additionally, for protocol version 2 a comma-separated list of ciphers can
be specified in order of preference. Protocol version 2 supports
3DES, Blowfish and CAST128 in CBC mode and Arcfour.
.It Fl e Ar ch|^ch|none
Sets the escape character for sessions with a pty (default:
.Ql ~ ) .
@ -324,7 +374,7 @@ This is useful if
.Nm
is going to ask for passwords or passphrases, but the user
wants it in the background.
This implies
This implies
.Fl n .
The recommended way to start X11 programs at a remote site is with
something like
@ -332,10 +382,10 @@ something like
.It Fl g
Allows remote hosts to connect to local forwarded ports.
.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.
Default is
.Pa \&.ssh/identity
Default is
.Pa $HOME/.ssh/identity
in the user's home directory.
Identity files may also be specified on
a per-host basis in the configuration file.
@ -457,6 +507,10 @@ from the local machine.
Port forwardings can also be specified in the configuration file.
Privileged ports can be forwarded only when
logging in as root on the remote machine.
.It Fl 2
Forces
.Nm
to try protocol version 2 only.
.It Fl 4
Forces
.Nm
@ -550,6 +604,12 @@ and
are supported.
The default is
.Dq 3des .
.It Cm Ciphers
Specifies the ciphers allowed for protocol version 2
in order of preference.
Multiple ciphers must be comma-separated.
The default is
.Dq 3des-cbc,blowfish-cbc,arcfour,cast128-cbc .
.It Cm Compression
Specifies whether to use compression.
The argument must be
@ -567,6 +627,15 @@ Specifies the number of tries (one per second) to make before falling
back to rsh or exiting.
The argument must be an integer.
This may be useful in scripts if the connection sometimes fails.
.It Cm DSAAuthentication
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
Sets the escape character (default:
.Ql ~ ) .
@ -604,7 +673,7 @@ Specifies whether X11 connections will be automatically redirected
over the secure channel and
.Ev DISPLAY
set.
The argument must be
The argument must be
.Dq yes
or
.Dq no .
@ -632,7 +701,7 @@ specifications).
.It Cm IdentityFile
Specifies the file from which the user's RSA authentication identity
is read (default
.Pa .ssh/identity
.Pa $HOME/.ssh/identity
in the user's home directory).
Additionally, any identities represented by the authentication agent
will be used for authentication.
@ -641,6 +710,16 @@ 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 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
Specifies whether the system should send keepalive messages to the
other side.
@ -696,9 +775,25 @@ The argument to this keyword must be
.Dq yes
or
.Dq no .
Note that this option applies to both protocol version 1 and 2.
.It Cm Port
Specifies the port number to connect on the remote host.
Default is 22.
.It Cm Protocol
Specifies the protocol versions
.Nm
should support in order of preference.
The possible values are
.Dq 1
and
.Dq 2 .
Multiple versions must be comma-separated.
The default is
.Dq 1,2 .
This means that
.Nm
tries version 1 and falls back to version 2
if version 1 is not available.
.It Cm ProxyCommand
Specifies the command to use to connect to the server.
The command
@ -763,6 +858,7 @@ or
RSA authentication will only be
attempted if the identity file exists, or an authentication agent is
running.
Note that this option applies to protocol version 1 only.
.It Cm SkeyAuthentication
Specifies whether to use
.Xr skey 1
@ -779,10 +875,14 @@ If this flag is set to
.Nm
ssh will never automatically add host keys to the
.Pa $HOME/.ssh/known_hosts
file, and refuses to connect hosts whose host key has changed.
and
.Pa $HOME/.ssh/known_hosts2
files, and refuses to connect hosts whose host key has changed.
This provides maximum protection against trojan horse attacks.
However, it can be somewhat annoying if you don't have good
.Pa /etc/ssh/ssh_known_hosts
and
.Pa /etc/ssh/ssh_known_hosts2
files installed and frequently
connect new hosts.
Basically this option forces the user to manually
@ -841,7 +941,7 @@ will normally set the following environment variables:
The
.Ev DISPLAY
variable indicates the location of the X11 server.
It is automatically set by
It is automatically set by
.Nm
to point to a value of the form
.Dq hostname:n
@ -902,28 +1002,36 @@ in
.Pa /etc/ssh/ssh_known_hosts ) .
See
.Xr sshd 8 .
.It Pa $HOME/.ssh/identity
Contains the RSA authentication identity of the user.
This file
contains sensitive data and should be readable by the user but not
.It Pa $HOME/.ssh/identity, $HOME/.ssh/id_dsa
Contains the RSA and the DSA authentication identity of the user.
These files
contain sensitive data and should be readable by the user but not
accessible by others (read/write/execute).
Note that
.Nm
ignores this file if it is accessible by others.
ignores a private key file if it is accessible by others.
It is possible to specify a passphrase when
generating the key; the passphrase will be used to encrypt the
sensitive part of this file using 3DES.
.It Pa $HOME/.ssh/identity.pub
.It Pa $HOME/.ssh/identity.pub, $HOME/.ssh/id_dsa.pub
Contains the public key for authentication (public part of the
identity file in human-readable form).
The contents of this file should be added to
The contents of the
.Pa $HOME/.ssh/identity.pub
file should be added to
.Pa $HOME/.ssh/authorized_keys
on all machines
where you wish to log in using RSA authentication.
This file is not
The contents of the
.Pa $HOME/.ssh/id_dsa.pub
file should be added to
.Pa $HOME/.ssh/authorized_keys2
on all machines
where you wish to log in using DSA authentication.
These files are not
sensitive and can (but need not) be readable by anyone.
This file is
never used automatically and is not necessary; it is only provided for
These files are
never used automatically and are not necessary; they is only provided for
the convenience of the user.
.It Pa $HOME/.ssh/config
This is the per-user configuration file.
@ -945,9 +1053,17 @@ modulus, public exponent, modulus, and comment fields, separated by
spaces).
This file is not highly sensitive, but the recommended
permissions are read/write for the user, and not accessible by others.
.It Pa /etc/ssh/ssh_known_hosts
.It Pa $HOME/.ssh/authorized_keys2
Lists the DSA keys that can be used for logging in as this user.
This file is not highly sensitive, but the recommended
permissions are read/write for the user, and not accessible by others.
.It Pa /etc/ssh/ssh_known_hosts, /etc/ssh/ssh_known_hosts2
Systemwide list of known host keys.
This file should be prepared by the
.Pa /etc/ssh_known_hosts
contains RSA and
.Pa /etc/ssh_known_hosts2
contains DSA keys.
These files should be prepared by the
system administrator to contain the public host keys of all machines in the
organization.
This file should be world-readable.
@ -1006,7 +1122,7 @@ you can store it in
.Pa $HOME/.ssh/known_hosts .
The easiest way to do this is to
connect back to the client from the server machine using ssh; this
will automatically add the host key inxi
will automatically add the host key to
.Pa $HOME/.ssh/known_hosts .
.It Pa $HOME/.shosts
This file is used exactly the same way as
@ -1034,7 +1150,7 @@ Additionally, successful RSA host authentication is normally
required.
This file should only be writable by root.
.It Pa /etc/ssh/shosts.equiv
This file is processed exactly as
This file is processed exactly as
.Pa /etc/hosts.equiv .
This file may be useful to permit logins using
.Nm
@ -1068,6 +1184,7 @@ but with bugs removed and newer features re-added.
Rapidly after the
1.2.12 release, newer versions of the original ssh bore successively
more restrictive licenses, and thus demand for a free version was born.
.Pp
This version of OpenSSH
.Bl -bullet
.It
@ -1077,8 +1194,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, making it compatible with
all other ssh protocol 1 clients and servers.
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
@ -1094,6 +1211,8 @@ are required for proper operation.
.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
.Xr rlogin 1 ,
.Xr rsh 1 ,

View File

@ -13,7 +13,11 @@
*/
#include "includes.h"
RCSID("$Id: ssh.c,v 1.43 2000/03/23 21:52:02 markus Exp $");
RCSID("$Id: ssh.c,v 1.51 2000/05/08 17:12:15 markus Exp $");
#include <openssl/evp.h>
#include <openssl/dsa.h>
#include <openssl/rsa.h>
#include "xmalloc.h"
#include "ssh.h"
@ -23,6 +27,14 @@ RCSID("$Id: ssh.c,v 1.43 2000/03/23 21:52:02 markus Exp $");
#include "readconf.h"
#include "uidswap.h"
#include "ssh2.h"
#include "compat.h"
#include "channels.h"
#include "key.h"
#include "authfile.h"
extern char *__progname;
/* Flag indicating whether IPv4 or IPv6. This can be set on the command line.
Default value is AF_UNSPEC means both IPv4 and IPv6. */
int IPv4or6 = AF_UNSPEC;
@ -30,8 +42,13 @@ int IPv4or6 = AF_UNSPEC;
/* Flag indicating whether debug mode is on. This can be set on the command line. */
int debug_flag = 0;
/* Flag indicating whether a tty should be allocated */
int tty_flag = 0;
/* don't exec a shell */
int no_shell_flag = 0;
int no_tty_flag = 0;
/*
* Flag indicating that nothing should be read from stdin. This can be set
* on the command line.
@ -81,6 +98,9 @@ RSA *host_private_key = NULL;
/* Original real UID. */
uid_t original_real_uid;
/* command to be executed */
Buffer command;
/* Prints a help message to the user. This function never returns. */
void
@ -98,6 +118,7 @@ usage()
fprintf(stderr, " -X Enable X11 connection forwarding.\n");
fprintf(stderr, " -i file Identity for RSA authentication (default: ~/.ssh/identity).\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, " -v Verbose; display verbose debugging messages.\n");
fprintf(stderr, " -V Display version number only.\n");
fprintf(stderr, " -P Don't allocate a privileged port.\n");
@ -114,9 +135,11 @@ usage()
fprintf(stderr, " These cause %s to listen for connections on a port, and\n", av0);
fprintf(stderr, " forward them to the other side by connecting to host:port.\n");
fprintf(stderr, " -C Enable compression.\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, " -4 Use IPv4 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");
exit(1);
}
@ -162,23 +185,22 @@ rsh_connect(char *host, char *user, Buffer * command)
exit(1);
}
int ssh_session(void);
int ssh_session2(void);
/*
* Main program for the ssh client.
*/
int
main(int ac, char **av)
{
int i, opt, optind, type, exit_status, ok, authfd;
int i, opt, optind, exit_status, ok;
u_short fwd_port, fwd_host_port;
char *optarg, *cp, buf[256];
Buffer command;
struct winsize ws;
struct stat st;
struct passwd *pw, pwcopy;
int interactive = 0, dummy;
int have_pty = 0;
int dummy;
uid_t original_effective_uid;
int plen;
/*
* Save the original real uid. It will be needed later (uid-swapping
@ -234,8 +256,8 @@ main(int ac, char **av)
if (host)
break;
if ((cp = strchr(av[optind], '@'))) {
if(cp == av[optind])
usage();
if(cp == av[optind])
usage();
options.user = av[optind];
*cp = '\0';
host = ++cp;
@ -259,39 +281,34 @@ main(int ac, char **av)
optarg = NULL;
}
switch (opt) {
case '2':
options.protocol = SSH_PROTO_2;
break;
case '4':
IPv4or6 = AF_INET;
break;
case '6':
IPv4or6 = AF_INET6;
break;
case 'n':
stdin_null_flag = 1;
break;
case 'f':
fork_after_authentication_flag = 1;
stdin_null_flag = 1;
break;
case 'x':
options.forward_x11 = 0;
break;
case 'X':
options.forward_x11 = 1;
break;
case 'g':
options.gateway_ports = 1;
break;
case 'P':
options.use_privileged_port = 0;
break;
case 'a':
options.forward_agent = 0;
break;
@ -314,26 +331,24 @@ main(int ac, char **av)
options.identity_files[options.num_identity_files++] =
xstrdup(optarg);
break;
case 't':
tty_flag = 1;
break;
case 'v':
case 'V':
fprintf(stderr, "SSH Version %s, protocol version %d.%d.\n",
SSH_VERSION, PROTOCOL_MAJOR, PROTOCOL_MINOR);
fprintf(stderr, "Compiled with SSL.\n");
fprintf(stderr, "SSH Version %s, protocol versions %d.%d/%d.%d.\n",
SSH_VERSION,
PROTOCOL_MAJOR_1, PROTOCOL_MINOR_1,
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2);
fprintf(stderr, "Compiled with SSL (0x%8.8lx).\n", SSLeay());
if (opt == 'V')
exit(0);
debug_flag = 1;
options.log_level = SYSLOG_LEVEL_DEBUG;
break;
case 'q':
options.log_level = SYSLOG_LEVEL_QUIET;
break;
case 'e':
if (optarg[0] == '^' && optarg[2] == 0 &&
(unsigned char) optarg[1] >= 64 && (unsigned char) optarg[1] < 128)
@ -347,23 +362,26 @@ main(int ac, char **av)
exit(1);
}
break;
case 'c':
options.cipher = cipher_number(optarg);
if (options.cipher == -1) {
fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
exit(1);
if (ciphers_valid(optarg)) {
/* SSH2 only */
options.ciphers = xstrdup(optarg);
options.cipher = SSH_CIPHER_ILLEGAL;
} else {
/* SSH1 only */
options.cipher = cipher_number(optarg);
if (options.cipher == -1) {
fprintf(stderr, "Unknown cipher type '%s'\n", optarg);
exit(1);
}
}
break;
case 'p':
options.port = atoi(optarg);
break;
case 'l':
options.user = optarg;
break;
case 'R':
if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf,
&fwd_host_port) != 3 &&
@ -375,7 +393,6 @@ main(int ac, char **av)
}
add_remote_forward(&options, fwd_port, buf, fwd_host_port);
break;
case 'L':
if (sscanf(optarg, "%hu/%255[^/]/%hu", &fwd_port, buf,
&fwd_host_port) != 3 &&
@ -387,18 +404,22 @@ main(int ac, char **av)
}
add_local_forward(&options, fwd_port, buf, fwd_host_port);
break;
case 'C':
options.compression = 1;
break;
case 'N':
no_shell_flag = 1;
no_tty_flag = 1;
break;
case 'T':
no_tty_flag = 1;
break;
case 'o':
dummy = 1;
if (process_config_line(&options, host ? host : "", optarg,
"command-line", 0, &dummy) != 0)
exit(1);
break;
default:
usage();
}
@ -408,15 +429,8 @@ main(int ac, char **av)
if (!host)
usage();
/* check if RSA support exists */
if (rsa_alive() == 0) {
extern char *__progname;
OpenSSL_add_all_algorithms();
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
/* Initialize the command to execute on remote host. */
buffer_init(&command);
@ -452,6 +466,10 @@ main(int ac, char **av)
fprintf(stderr, "Pseudo-terminal will not be allocated because stdin is not a terminal.\n");
tty_flag = 0;
}
/* force */
if (no_tty_flag)
tty_flag = 0;
/* Get user data. */
pw = getpwuid(original_real_uid);
if (!pw) {
@ -485,6 +503,20 @@ main(int ac, char **av)
/* reinit */
log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 0);
/* 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)
options.user = xstrdup(pw->pw_name);
@ -551,9 +583,12 @@ main(int ac, char **av)
* authentication. This must be done before releasing extra
* privileges, because the file is only readable by root.
*/
if (ok) {
if (ok && (options.protocol & SSH_PROTO_1)) {
Key k;
host_private_key = RSA_new();
if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL))
k.type = KEY_RSA;
k.rsa = host_private_key;
if (load_private_key(HOST_KEY_FILE, "", &k, NULL))
host_private_key_loaded = 1;
}
/*
@ -599,15 +634,22 @@ main(int ac, char **av)
exit(1);
}
/* Expand ~ in options.identity_files. */
/* XXX mem-leaks */
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. */
options.system_hostfile = tilde_expand_filename(options.system_hostfile,
original_real_uid);
original_real_uid);
options.user_hostfile = tilde_expand_filename(options.user_hostfile,
original_real_uid);
original_real_uid);
options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2,
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. */
ssh_login(host_private_key_loaded, host_private_key,
@ -617,6 +659,62 @@ main(int ac, char **av)
if (host_private_key_loaded)
RSA_free(host_private_key); /* Destroys contents safely */
exit_status = compat20 ? ssh_session2() : ssh_session();
packet_close();
return exit_status;
}
void
x11_get_proto(char *proto, int proto_len, char *data, int data_len)
{
char line[512];
FILE *f;
int got_data = 0, i;
#ifdef XAUTH_PATH
/* Try to get Xauthority information for the display. */
snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
XAUTH_PATH, getenv("DISPLAY"));
f = popen(line, "r");
if (f && fgets(line, sizeof(line), f) &&
sscanf(line, "%*s %s %s", proto, data) == 2)
got_data = 1;
if (f)
pclose(f);
#endif /* XAUTH_PATH */
/*
* If we didn't get authentication data, just make up some
* data. The forwarding code will check the validity of the
* response anyway, and substitute this data. The X11
* server, however, will ignore this fake data and use
* whatever authentication mechanisms it was using otherwise
* for the local connection.
*/
if (!got_data) {
u_int32_t rand = 0;
strlcpy(proto, "MIT-MAGIC-COOKIE-1", proto_len);
for (i = 0; i < 16; i++) {
if (i % 4 == 0)
rand = arc4random();
snprintf(data + 2 * i, data_len - 2 * i, "%02x", rand & 0xff);
rand >>= 8;
}
}
}
int
ssh_session(void)
{
int type;
int i;
int plen;
int interactive = 0;
int have_tty = 0;
struct winsize ws;
int authfd;
char *cp;
/* Enable compression if requested. */
if (options.compression) {
debug("Requesting compression at level %d.", options.compression_level);
@ -670,7 +768,7 @@ main(int ac, char **av)
type = packet_read(&plen);
if (type == SSH_SMSG_SUCCESS) {
interactive = 1;
have_pty = 1;
have_tty = 1;
} else if (type == SSH_SMSG_FAILURE)
log("Warning: Remote host failed or refused to allocate a pseudo tty.");
else
@ -678,56 +776,22 @@ main(int ac, char **av)
}
/* Request X11 forwarding if enabled and DISPLAY is set. */
if (options.forward_x11 && getenv("DISPLAY") != NULL) {
char line[512], proto[512], data[512];
FILE *f;
int forwarded = 0, got_data = 0, i;
#ifdef XAUTH_PATH
/* Try to get Xauthority information for the display. */
snprintf(line, sizeof line, "%.100s list %.200s 2>/dev/null",
XAUTH_PATH, getenv("DISPLAY"));
f = popen(line, "r");
if (f && fgets(line, sizeof(line), f) &&
sscanf(line, "%*s %s %s", proto, data) == 2)
got_data = 1;
if (f)
pclose(f);
#endif /* XAUTH_PATH */
/*
* If we didn't get authentication data, just make up some
* data. The forwarding code will check the validity of the
* response anyway, and substitute this data. The X11
* server, however, will ignore this fake data and use
* whatever authentication mechanisms it was using otherwise
* for the local connection.
*/
if (!got_data) {
u_int32_t rand = 0;
strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto);
for (i = 0; i < 16; i++) {
if (i % 4 == 0)
rand = arc4random();
snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff);
rand >>= 8;
}
}
/*
* Got local authentication reasonable information. Request
* forwarding with authentication spoofing.
*/
char proto[512], data[512];
/* Get reasonable local authentication information. */
x11_get_proto(proto, sizeof proto, data, sizeof data);
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication spoofing.");
x11_request_forwarding_with_spoofing(proto, data);
x11_request_forwarding_with_spoofing(0, proto, data);
/* Read response from the server. */
type = packet_read(&plen);
if (type == SSH_SMSG_SUCCESS) {
forwarded = 1;
interactive = 1;
} else if (type == SSH_SMSG_FAILURE)
} else if (type == SSH_SMSG_FAILURE) {
log("Warning: Remote host denied X11 forwarding.");
else
} else {
packet_disconnect("Protocol error waiting for X11 forwarding");
}
}
/* Tell the packet module whether this is an interactive session. */
packet_set_interactive(interactive, options.keepalives);
@ -757,7 +821,7 @@ main(int ac, char **av)
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,
options.local_forwards[i].host_port,
options.gateway_ports);
}
@ -770,11 +834,11 @@ main(int ac, char **av)
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);
options.remote_forwards[i].host_port);
}
/* If requested, let ssh continue in the background. */
if (fork_after_authentication_flag)
if (fork_after_authentication_flag)
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
@ -799,11 +863,114 @@ main(int ac, char **av)
}
/* Enter the interactive session. */
exit_status = client_loop(have_pty, tty_flag ? options.escape_char : -1);
/* Close the connection to the remote host. */
packet_close();
/* Exit with the status returned by the program on the remote side. */
exit(exit_status);
return client_loop(have_tty, tty_flag ? options.escape_char : -1);
}
void
init_local_fwd(void)
{
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);
channel_request_local_forwarding(options.local_forwards[i].port,
options.local_forwards[i].host,
options.local_forwards[i].host_port,
options.gateway_ports);
}
}
extern void client_set_session_ident(int id);
void
client_init(int id, void *arg)
{
int len;
debug("client_init id %d arg %d", id, (int)arg);
if (no_shell_flag)
goto done;
if (tty_flag) {
struct winsize ws;
char *cp;
cp = getenv("TERM");
if (!cp)
cp = "";
/* Store window size in the packet. */
if (ioctl(fileno(stdin), TIOCGWINSZ, &ws) < 0)
memset(&ws, 0, sizeof(ws));
channel_request_start(id, "pty-req", 0);
packet_put_cstring(cp);
packet_put_int(ws.ws_col);
packet_put_int(ws.ws_row);
packet_put_int(ws.ws_xpixel);
packet_put_int(ws.ws_ypixel);
packet_put_cstring(""); /* XXX: encode terminal modes */
packet_send();
/* XXX wait for reply */
}
if (options.forward_x11 &&
getenv("DISPLAY") != NULL) {
char proto[512], data[512];
/* Get reasonable local authentication information. */
x11_get_proto(proto, sizeof proto, data, sizeof data);
/* Request forwarding with authentication spoofing. */
debug("Requesting X11 forwarding with authentication spoofing.");
x11_request_forwarding_with_spoofing(id, proto, data);
/* XXX wait for reply */
}
len = buffer_len(&command);
if (len > 0) {
if (len > 900)
len = 900;
debug("Sending command: %.*s", len, buffer_ptr(&command));
channel_request_start(id, "exec", 0);
packet_put_string(buffer_ptr(&command), len);
packet_send();
} else {
channel_request(id, "shell", 0);
}
/* channel_callback(id, SSH2_MSG_OPEN_CONFIGMATION, client_init, 0); */
done:
/* register different callback, etc. XXX */
client_set_session_ident(id);
}
int
ssh_session2(void)
{
int window, packetmax, id;
int in = dup(STDIN_FILENO);
int out = dup(STDOUT_FILENO);
int err = dup(STDERR_FILENO);
if (in < 0 || out < 0 || err < 0)
fatal("dump in/out/err failed");
/* should be pre-session */
init_local_fwd();
window = 32*1024;
if (tty_flag) {
packetmax = window/8;
} else {
window *= 2;
packetmax = window/2;
}
id = channel_new(
"session", SSH_CHANNEL_OPENING, in, out, err,
window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"));
channel_open(id);
channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, client_init, (void *)0);
return client_loop(tty_flag, tty_flag ? options.escape_char : -1);
}

View File

@ -1,20 +1,20 @@
/*
*
*
* ssh.h
*
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
*
*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*
*
* Created: Fri Mar 17 17:09:37 1995 ylo
*
*
* Generic header file for ssh.
*
*
* $FreeBSD$
*/
/* RCSID("$Id: ssh.h,v 1.34 2000/03/23 22:15:33 markus Exp $"); */
/* RCSID("$Id: ssh.h,v 1.45 2000/05/08 17:12:16 markus Exp $"); */
#ifndef SSH_H
#define SSH_H
@ -23,6 +23,7 @@
#include "cipher.h"
/*
* XXX
* The default cipher used if IDEA is not supported by the remote host. It is
* recommended that this be one of the mandatory ciphers (DES, 3DES), though
* that is not required.
@ -47,14 +48,16 @@
/*
* Major protocol version. Different version indicates major incompatiblity
* that prevents communication.
*/
#define PROTOCOL_MAJOR 1
/*
*
* Minor protocol version. Different version indicates minor incompatibility
* that does not prevent interoperation.
*/
#define PROTOCOL_MINOR 5
#define PROTOCOL_MAJOR_1 1
#define PROTOCOL_MINOR_1 5
/* We support both SSH1 and SSH2 */
#define PROTOCOL_MAJOR_2 2
#define PROTOCOL_MINOR_2 0
/*
* Name for the service. The port named by this service overrides the
@ -70,6 +73,7 @@
* 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
@ -78,6 +82,7 @@
#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 SSH_PROGRAM "/usr/bin/ssh"
@ -99,12 +104,14 @@
* 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
@ -123,6 +130,7 @@
* 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
@ -259,7 +267,7 @@
* 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
unsigned long
get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize);
@ -267,15 +275,15 @@ get_last_login_time(uid_t uid, const char *logname,
* Records that the user has logged in. This does many things normally done
* by login(1).
*/
void
record_login(int pid, const char *ttyname, const char *user, uid_t uid,
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(int pid, const char *ttyname);
void record_logout(pid_t pid, const char *ttyname);
/*------------ definitions for sshconnect.c ----------*/
@ -288,7 +296,7 @@ void record_logout(int pid, const char *ttyname);
* and zero on failure. If the connection is successful, this calls
* packet_set_connection for the connection.
*/
int
int
ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
u_short port, int connection_attempts,
int anonymous, uid_t original_real_uid,
@ -303,7 +311,7 @@ ssh_connect(const char *host, struct sockaddr_storage * hostaddr,
* references from the packet module).
*/
void
void
ssh_login(int host_key_valid, RSA * host_key, const char *host,
struct sockaddr * hostaddr, uid_t original_real_uid);
@ -320,7 +328,7 @@ 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
int
auth_rhosts_rsa(struct passwd * pw, const char *client_user, RSA* client_host_key);
/*
@ -383,36 +391,6 @@ int auth_rsa_challenge_dialog(RSA *pk);
*/
char *read_passphrase(const char *prompt, int from_stdin);
/*
* Saves the authentication (private) key in a file, encrypting it with
* passphrase. The identification of the file (lowest 64 bits of n) will
* precede the key to provide identification of the key without needing a
* passphrase.
*/
int
save_private_key(const char *filename, const char *passphrase,
RSA * private_key, const char *comment);
/*
* Loads the public part of the key file (public key and comment). Returns 0
* if an error occurred; zero if the public key was successfully read. The
* comment of the key is returned in comment_return if it is non-NULL; the
* caller must free the value with xfree.
*/
int
load_public_key(const char *filename, RSA * pub,
char **comment_return);
/*
* 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. The comment of the key is returned in
* comment_return if it is non-NULL; the caller must free the value with
* xfree.
*/
int
load_private_key(const char *filename, const char *passphrase,
RSA * private_key, char **comment_return);
/*------------ Definitions for logging. -----------------------*/
@ -469,174 +447,7 @@ 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);
/*---------------- definitions for channels ------------------*/
/* Sets specific protocol options. */
void channel_set_options(int hostname_in_open);
/*
* Allocate a new channel object and set its type and socket. Remote_name
* must have been allocated with xmalloc; this will free it when the channel
* is freed.
*/
int channel_allocate(int type, int sock, char *remote_name);
/* Free the channel and close its socket. */
void channel_free(int channel);
/* Add any bits relevant to channels in select bitmasks. */
void channel_prepare_select(fd_set * readset, fd_set * writeset);
/*
* After select, perform any appropriate operations for channels which have
* events pending.
*/
void channel_after_select(fd_set * readset, fd_set * writeset);
/* If there is data to send to the connection, send some of it now. */
void channel_output_poll(void);
/*
* This is called when a packet of type CHANNEL_DATA has just been received.
* The message type has already been consumed, but channel number and data is
* still there.
*/
void channel_input_data(int payload_len);
/* Returns true if no channel has too much buffered data. */
int channel_not_very_much_buffered_data(void);
/* This is called after receiving CHANNEL_CLOSE. */
void channel_input_close(void);
/* This is called after receiving CHANNEL_CLOSE_CONFIRMATION. */
void channel_input_close_confirmation(void);
/* This is called after receiving CHANNEL_OPEN_CONFIRMATION. */
void channel_input_open_confirmation(void);
/* This is called after receiving CHANNEL_OPEN_FAILURE from the other side. */
void channel_input_open_failure(void);
/* This closes any sockets that are listening for connections; this removes
any unix domain sockets. */
void channel_stop_listening(void);
/*
* Closes the sockets of all channels. This is used to close extra file
* descriptors after a fork.
*/
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. */
int channel_still_open(void);
/*
* Returns a string containing a list of all open channels. The list is
* suitable for displaying to the user. It uses crlf instead of newlines.
* The caller should free the string with xfree.
*/
char *channel_open_message(void);
/*
* 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
* error.
*/
void
channel_request_local_forwarding(u_short port, const char *host,
u_short remote_port, int gateway_ports);
/*
* Initiate forwarding of connections to port "port" on remote host through
* the secure channel to host:port from local side. This never returns if
* there was an error. This registers that open requests for that port are
* permitted.
*/
void
channel_request_remote_forwarding(u_short port, const char *host,
u_short remote_port);
/*
* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually
* called by the server, because the user could connect to any port anyway,
* and the server has no way to know but to trust the client anyway.
*/
void channel_permit_all_opens(void);
/*
* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
* listening for the port, and sends back a success reply (or disconnect
* message if there was an error). This never returns if there was an error.
*/
void channel_input_port_forward_request(int is_root);
/*
* This is called after receiving PORT_OPEN message. This attempts to
* connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION
* or CHANNEL_OPEN_FAILURE.
*/
void channel_input_port_open(int payload_len);
/*
* Creates a port for X11 connections, and starts listening for it. Returns
* the display name, or NULL if an error was encountered.
*/
char *x11_create_display(int screen);
/*
* Creates an internet domain socket for listening for X11 connections.
* Returns a suitable value for the DISPLAY variable, or NULL if an error
* occurs.
*/
char *x11_create_display_inet(int screen, int x11_display_offset);
/*
* This is called when SSH_SMSG_X11_OPEN is received. The packet contains
* the remote channel number. We should do whatever we want, and respond
* with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE.
*/
void x11_input_open(int payload_len);
/*
* Requests forwarding of X11 connections. This should be called on the
* client only.
*/
void x11_request_forwarding(void);
/*
* Requests forwarding for X11 connections, with authentication spoofing.
* This should be called in the client only.
*/
void x11_request_forwarding_with_spoofing(const char *proto, const char *data);
/* Sends a message to the server to request authentication fd forwarding. */
void auth_request_forwarding(void);
/*
* Returns the name of the forwarded authentication socket. Returns NULL if
* there is no forwarded authentication socket. The returned value points to
* a static buffer.
*/
char *auth_get_socket_name(void);
/*
* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
* This starts forwarding authentication requests.
*/
void auth_input_request_forwarding(struct passwd * pw);
/* This is called to process an SSH_SMSG_AGENT_OPEN message. */
void auth_input_open_request(void);
/*
* Returns true if the given string matches the pattern (which may contain ?
* and * as wildcards), and zero if it does not match.
*/
int match_pattern(const char *s, const char *pattern);
/* ---- misc */
/*
* Expands tildes in the file name. Returns data allocated by xmalloc.
@ -651,7 +462,8 @@ char *tilde_expand_filename(const char *filename, uid_t my_uid);
* (of the child program), and reads from stdout and stderr (of the child
* program).
*/
void server_loop(int pid, int fdin, int fdout, int fderr);
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);
@ -695,14 +507,14 @@ int auth_krb4_password(struct passwd * pw, const char *password);
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);
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 <skey.h>
#include <opie.h>
char *skey_fake_keyinfo(char *username);
int auth_skey_password(struct passwd * pw, const char *password);
#endif /* SKEY */

View File

@ -28,5 +28,6 @@
# StrictHostKeyChecking no
# IdentityFile ~/.ssh/identity
# Port 22
# Protocol 2,1
# Cipher blowfish
# EscapeChar ~

File diff suppressed because it is too large Load Diff

View File

@ -6,6 +6,7 @@
* Code to connect to a remote host, and to perform the client side of the
* login (authentication) dialog.
*
* $FreeBSD$
*/
#include "includes.h"
@ -362,7 +363,7 @@ try_rhosts_rsa_authentication(const char *local_user, RSA * host_key)
#ifdef KRB4
int
try_kerberos_authentication()
try_krb4_authentication()
{
KTEXT_ST auth; /* Kerberos data */
char *reply;
@ -405,7 +406,7 @@ try_kerberos_authentication()
des_key_sched((des_cblock *) cred.session, schedule);
/* Send authentication info to server. */
packet_start(SSH_CMSG_AUTH_KERBEROS);
packet_start(SSH_CMSG_AUTH_KRB4);
packet_put_string((char *) auth.dat, auth.length);
packet_send();
packet_write_wait();
@ -430,13 +431,13 @@ try_kerberos_authentication()
type = packet_read(&plen);
switch (type) {
case SSH_SMSG_FAILURE:
/* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
/* Should really be SSH_SMSG_AUTH_KRB4_FAILURE */
debug("Kerberos V4 authentication failed.");
return 0;
break;
case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
/* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
case SSH_SMSG_AUTH_KRB4_RESPONSE:
/* SSH_SMSG_AUTH_KRB4_SUCCESS */
debug("Kerberos V4 authentication accepted.");
/* Get server's response. */
@ -479,7 +480,7 @@ try_kerberos_authentication()
#ifdef AFS
int
send_kerberos_tgt()
send_krb4_tgt()
{
CREDENTIALS *creds;
char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
@ -508,7 +509,7 @@ send_kerberos_tgt()
creds_to_radix(creds, (unsigned char *)buffer, sizeof buffer);
xfree(creds);
packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
packet_start(SSH_CMSG_HAVE_KRB4_TGT);
packet_put_string(buffer, strlen(buffer));
packet_send();
packet_write_wait();
@ -927,11 +928,11 @@ ssh_userauth(
#ifdef AFS
/* Try Kerberos tgt passing if the server supports it. */
if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
options.kerberos_tgt_passing) {
if ((supported_authentications & (1 << SSH_PASS_KRB4_TGT)) &&
options.krb4_tgt_passing) {
if (options.cipher == SSH_CIPHER_NONE)
log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
(void) send_kerberos_tgt();
(void) send_krb4_tgt();
}
/* Try AFS token passing if the server supports it. */
if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
@ -943,10 +944,10 @@ ssh_userauth(
#endif /* AFS */
#ifdef KRB4
if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
options.kerberos_authentication) {
if ((supported_authentications & (1 << SSH_AUTH_KRB4)) &&
options.krb4_authentication) {
debug("Trying Kerberos authentication.");
if (try_kerberos_authentication()) {
if (try_krb4_authentication()) {
/* The server should respond with success or failure. */
type = packet_read(&payload_len);
if (type == SSH_SMSG_SUCCESS)
@ -957,6 +958,35 @@ ssh_userauth(
}
#endif /* KRB4 */
#ifdef KRB5
if ((supported_authentications & (1 << SSH_AUTH_KRB5)) &&
options.krb5_authentication){
krb5_context ssh_context = NULL;
krb5_auth_context auth_context = NULL;
debug("Trying Kerberos V5 authentication.");
if (try_krb5_authentication(&ssh_context, &auth_context)) {
type = packet_read(&payload_len);
if (type == SSH_SMSG_SUCCESS) {
if ((supported_authentications & (1 << SSH_PASS_KRB5_TGT)) &&
options.krb5_tgt_passing) {
if (options.cipher == SSH_CIPHER_NONE)
log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
send_krb5_tgt(ssh_context, auth_context);
}
krb5_auth_con_free(ssh_context, auth_context);
krb5_free_context(ssh_context);
return;
}
if (type != SSH_SMSG_FAILURE)
packet_disconnect("Protocol error: got %d in response to Kerberos5 auth", type);
}
}
#endif /* KRB5 */
/*
* Use rhosts authentication if running in privileged socket and we
* do not wish to remain anonymous.

View File

@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\"
.\" $Id: sshd.8,v 1.37 2000/03/24 03:04:46 brad Exp $
.\" $Id: sshd.8,v 1.51 2000/05/08 17:42:31 hugh Exp $
.\" $FreeBSD$
.\"
.Dd September 25, 1999
@ -28,11 +28,11 @@
.Op Fl k Ar key_gen_time
.Op Fl p Ar port
.Op Fl V Ar client_protocol_id
.Sh DESCRIPTION
.Sh DESCRIPTION
.Nm
(Secure Shell Daemon) is the daemon program for
(Secure Shell Daemon) is the daemon program for
.Xr ssh 1 .
Together these programs replace rlogin and rsh programs, and
Together these programs replace rlogin and rsh, and
provide secure encrypted communications between two untrusted hosts
over an insecure network.
The programs are intended to be as easy to
@ -47,9 +47,14 @@ daemon for each incoming connection.
The forked daemons handle
key exchange, encryption, authentication, command execution,
and data exchange.
.Pp
This implementation of
.Nm
supports both SSH protocol version 1 and 2 simultaneously.
.Nm
works as follows.
.Pp
.Ss SSH protocol version 1
.Pp
Each host has a host-specific RSA key
(normally 1024 bits) used to identify the host.
Additionally, when
@ -57,20 +62,20 @@ the daemon starts, it generates a server RSA key (normally 768 bits).
This key is normally regenerated every hour if it has been used, and
is never stored on disk.
.Pp
Whenever a client connects the daemon, the daemon sends its host
and server public keys to the client.
Whenever a client connects the daemon responds with its public
host and server keys.
The client compares the
host key against its own database to verify that it has not changed.
RSA host key against its own database to verify that it has not changed.
The client then generates a 256 bit random number.
It encrypts this
random number using both the host key and the server key, and sends
the encrypted number to the server.
Both sides then start to use this
Both sides then use this
random number as a session key which is used to encrypt all further
communications in the session.
The rest of the session is encrypted
using a conventional cipher, currently Blowfish and 3DES, with 3DES
being is used by default.
using a conventional cipher, currently Blowfish or 3DES, with 3DES
being used by default.
The client selects the encryption algorithm
to use from those offered by the server.
.Pp
@ -96,7 +101,29 @@ are disabled (thus completely disabling
.Xr rlogin 1
and
.Xr rsh 1
into that machine).
into the machine).
.Pp
.Ss SSH protocol version 2
.Pp
Version 2 works similar:
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.
Forward security is provided through a Diffie-Hellman key agreement.
This key agreement results in a shared session key.
The rest of the session is encrypted
using a symmetric cipher, currently
Blowfish, 3DES or CAST128 in CBC mode or Arcfour.
The client selects the encryption algorithm
to use from those offered by the server.
Additionally, session integrity is provided
through a cryptographic message authentication code
(hmac-sha1 or hmac-md5).
.Pp
Protocol version 2 provides a public key based
user authentication method (DSAAuthentication)
and conventional password authentication.
.Pp
.Ss Command execution and data forwarding
.Pp
If the client successfully authenticates itself, a dialog for
preparing the session is entered.
@ -149,7 +176,7 @@ If the client fails to authenticate the user within
this many seconds, the server disconnects and exits.
A value of zero indicates no limit.
.It Fl h Ar host_key_file
Specifies the file from which the host key is read (default
Specifies the file from which the RSA host key is read (default
.Pa /etc/ssh/ssh_host_key ) .
This option must be given if
.Nm
@ -158,7 +185,7 @@ host file is normally not readable by anyone but root).
.It Fl i
Specifies that
.Nm
is being run from inetd.
is being run from inetd.
.Nm
is normally not run
from inetd because it needs to generate the server key before it can
@ -189,9 +216,9 @@ authentication, and termination of each connection is logged.
Do not print an error message if RSA support is missing.
.It Fl V Ar client_protocol_id
SSH2 compatibility mode.
When this options is specified
When this option is specified
.Nm
assumes the client has sent the given version string
assumes the client has sent the supplied version string
and skips the
Protocol Version Identification Exchange.
.It Fl 4
@ -205,7 +232,7 @@ to use IPv6 addresses only.
.El
.Sh CONFIGURATION FILE
.Nm
reads configuration data from
reads configuration data from
.Pa /etc/ssh/sshd_config
(or the file specified with
.Fl f
@ -247,6 +274,11 @@ wildcards in the patterns.
Only user names are valid, a numerical user ID isn't recognized.
By default login is allowed regardless of the user name.
.Pp
.It Cm Ciphers
Specifies the ciphers allowed for protocol version 2.
Multiple ciphers must be comma-separated.
The default is
.Dq 3des-cbc,blowfish-cbc,arcfour,cast128-cbc .
.It Cm CheckMail
Specifies whether
.Nm
@ -301,24 +333,45 @@ and
can be used as wildcards in the patterns.
Only user names are valid, a numerical user ID isn't recognized.
By default login is allowed regardless of the user name.
.It Cm HostKey
Specifies the file containing the private host key (default
.Pa /etc/ssh/ssh_host_key ) .
.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
Specifies whether remote hosts are allowed to connect to ports
forwarded for the client.
The argument must be
.Dq yes
or
.Dq no .
The default is
.Dq no .
.It Cm HostDsaKey
Specifies the file containing the private DSA host key (default
.Pa /etc/ssh/ssh_host_dsa_key )
used by SSH protocol 2.0.
Note that
.Nm
does not start if this file is group/world-accessible.
disables protocol 2.0 if this file is group/world-accessible.
.It Cm HostKey
Specifies the file containing the private RSA host key (default
.Pa /etc/ssh/ssh_host_key )
used by SSH protocols 1.3 and 1.5.
Note that
.Nm
disables protocols 1.3 and 1.5 if this file is group/world-accessible.
.It Cm IgnoreRhosts
Specifies that
.Pa .rhosts
and
and
.Pa .shosts
files will not be used in authentication.
.Pa /etc/hosts.equiv
and
.Pa /etc/ssh/shosts.equiv
.Pa /etc/shosts.equiv
are still used.
The default is
The default is
.Dq yes .
.It Cm IgnoreUserKnownHosts
Specifies whether
@ -337,7 +390,7 @@ of the machines will be properly noticed.
However, this means that
connections will die if the route is down temporarily, and some people
find it annoying.
On the other hand, if keepalives are not send,
On the other hand, if keepalives are not sent,
sessions may hang indefinitely on the server, leaving
.Dq ghost
users and consuming server resources.
@ -369,7 +422,7 @@ Default is
.Dq yes .
.It Cm KerberosTgtPassing
Specifies whether a Kerberos TGT may be forwarded to the server.
Default is
Default is
.Dq no ,
as this only works when the Kerberos KDC is actually an AFS kaserver.
.It Cm KerberosTicketCleanup
@ -412,6 +465,7 @@ and is not recommended.
Specifies whether password authentication is allowed.
The default is
.Dq yes .
Note that this option applies to both protocol version 1 and 2.
.It Cm PermitEmptyPasswords
When password authentication is allowed, it specifies whether the
server allows login to accounts with empty password strings.
@ -437,6 +491,12 @@ option has been
specified will be allowed regardless of the value of this setting
(which may be useful for taking remote backups even if root login is
normally not allowed).
.It Cm PidFile
Specifies the file that contains the process identifier of the
.Nm
daemon.
The default is
.Pa /var/run/sshd.pid .
.It Cm Port
Specifies the port number that
.Nm
@ -446,7 +506,7 @@ Multiple options of this type are permitted.
.It Cm PrintMotd
Specifies whether
.Nm
should print
should print
.Pa /etc/motd
when a user logs in interactively.
(On some systems it is also printed by the shell,
@ -454,6 +514,17 @@ when a user logs in interactively.
or equivalent.)
The default is
.Dq yes .
.It Cm Protocol
Specifies the protocol versions
.Nm
should support.
The possible values are
.Dq 1
and
.Dq 2 .
Multiple versions must be comma-separated.
The default is
.Dq 1 .
.It Cm RandomSeed
Obsolete - accepted and ignored with a warning.
Random number generation uses other techniques.
@ -481,12 +552,13 @@ The default is
Specifies whether pure RSA authentication is allowed.
The default is
.Dq yes .
Note that this option applies to protocol version 1 only.
.It Cm ServerKeyBits
Defines the number of bits in the server key.
The minimum value is 512, and the default is 768.
.It Cm SkeyAuthentication
Specifies whether
.Xr skey 1
.Xr skey 1
authentication is allowed.
The default is
.Dq yes .
@ -536,12 +608,12 @@ does the following:
.Bl -enum -offset indent
.It
If the login is on a tty, and no command has been specified,
prints last login time and
prints last login time and
.Pa /etc/motd
(unless prevented in the configuration file or by
.Pa $HOME/.hushlogin ;
see the
.Sx FILES
.Sx FILES
section).
.It
If the login is on a tty, records login time.
@ -577,10 +649,14 @@ authentication protocol and cookie (if applicable) in standard input.
Runs user's shell or command.
.El
.Sh AUTHORIZED_KEYS FILE FORMAT
The
The
.Pa $HOME/.ssh/authorized_keys
file lists the RSA keys that are
permitted for RSA authentication.
permitted for RSA authentication in SSH protocols 1.3 and 1.5
Similarly, the
.Pa $HOME/.ssh/authorized_keys2
file lists the DSA keys that are
permitted for DSA authentication in SSH protocol 2.0.
Each line of the file contains one
key (empty lines and lines starting with a
.Ql #
@ -636,8 +712,8 @@ A quote may be included in the command by quoting it with a backslash.
This option might be useful
to restrict certain RSA keys to perform just a specific operation.
An example might be a key that permits remote backups but nothing else.
Notice that the client may specify TCP/IP and/or X11
forwardings unless they are explicitly prohibited.
Note that the client may specify TCP/IP and/or X11
forwarding unless they are explicitly prohibited.
.It Cm environment="NAME=value"
Specifies that the string is to be added to the environment when
logging in using this key.
@ -666,10 +742,12 @@ 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
.Ed
.Sh SSH_KNOWN_HOSTS FILE FORMAT
The
.Pa /etc/ssh/ssh_known_hosts
and
.Pa $HOME/.ssh/known_hosts
The
.Pa /etc/ssh/ssh_known_hosts ,
.Pa /etc/ssh/ssh_known_hosts2 ,
.Pa $HOME/.ssh/known_hosts ,
and
.Pa $HOME/.ssh/known_hosts2
files contain host public keys for all known hosts.
The global file should
be prepared by the administrator (optional), and the per-user file is
@ -690,7 +768,7 @@ to indicate negation: if the host name matches a negated
pattern, it is not accepted (by that line) even if it matched another
pattern on the line.
.Pp
Bits, exponent, and modulus are taken directly from the host key; they
Bits, exponent, and modulus are taken directly from the RSA host key; they
can be obtained, e.g., from
.Pa /etc/ssh/ssh_host_key.pub .
The optional comment field continues to the end of the line, and is not used.
@ -713,7 +791,7 @@ accepted if valid information can be found from either file.
Note that the lines in these files are typically hundreds of characters
long, and you definitely don't want to type in the host keys by hand.
Rather, generate them by a script
or by taking
or by taking
.Pa /etc/ssh/ssh_host_key.pub
and adding the host names at the front.
.Ss Examples
@ -758,6 +836,21 @@ it being world-readable if the user's home directory resides on an NFS
volume).
It is recommended that it not be accessible by others.
The format of this file is described above.
Users will place the contents of their
.Pa identity.pub
files into this file, as described in
.Xr ssh-keygen 1 .
.It Pa $HOME/.ssh/authorized_keys2
Lists the DSA keys that can be used to log into the user's account.
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
volume).
It is recommended that it not be accessible by others.
The format of this file is described above.
Users will place the contents of their
.Pa id_dsa.pub
files into this file, as described in
.Xr ssh-keygen 1 .
.It Pa "/etc/ssh/ssh_known_hosts" and "$HOME/.ssh/known_hosts"
These files are consulted when using rhosts with RSA host
authentication to check the public key of the host.
@ -770,7 +863,7 @@ should be world-readable, and
.Pa $HOME/.ssh/known_hosts
can but need not be world-readable.
.It Pa /etc/nologin
If this file exists,
If this file exists,
.Nm
refuses to let anyone except root log in.
The contents of the file
@ -897,6 +990,7 @@ but with bugs removed and newer features re-added.
Rapidly after the
1.2.12 release, newer versions of the original ssh bore successively
more restrictive licenses, and thus demand for a free version was born.
.Pp
This version of OpenSSH
.Bl -bullet
.It
@ -906,10 +1000,10 @@ 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, making it compatible with
all other ssh protocol 1 clients and servers.
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
contains added support for
.Xr kerberos 8
authentication and ticket passing.
.It
@ -920,12 +1014,17 @@ supports one-time password authentication with
The libraries described in
.Xr ssl 8
are required for proper operation.
.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
.Xr rlogin 1 ,
.Xr rsh 1 ,
.Xr scp 1 ,
.Xr ssh 1 ,
.Xr ssh-add 1 ,
.Xr ssh-agent 1 ,
.Xr ssh-keygen 1 ,
.Xr ssl 8
.Xr ssl 8 ,
.Xr rlogin 1 ,
.Xr rsh 1

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
# $FreeBSD$
Port 22
#Protocol 2,1
#ListenAddress 0.0.0.0
#ListenAddress ::
HostKey /etc/ssh/ssh_host_key