- Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure)

- [auth.c session.c sshd.c auth.h]
     split sshd.c -> auth.c session.c sshd.c plus cleanup and goto-removal
   - [bufaux.c bufaux.h]
     support ssh2 bignums
   - [channels.c channels.h clientloop.c sshd.c nchan.c nchan.h packet.c]
     [readconf.c ssh.c ssh.h serverloop.c]
     replace big switch() with function tables (prepare for ssh2)
   - [ssh2.h]
     ssh2 message type codes
   - [sshd.8]
     reorder Xr to avoid cutting
   - [serverloop.c]
     close(fdin) if fdin != fdout, shutdown otherwise, ok theo@
   - [channels.c]
     missing close
     allow bigger packets
   - [cipher.c cipher.h]
     support ssh2 ciphers
   - [compress.c]
     cleanup, less code
   - [dispatch.c dispatch.h]
     function tables for different message types
   - [log-server.c]
     do not log() if debuggin to stderr
     rename a cpp symbol, to avoid param.h collision
   - [mpaux.c]
     KNF
   - [nchan.c]
     sync w/ channels.c
This commit is contained in:
Damien Miller 2000-04-01 11:09:21 +10:00
Родитель 450a7a1ff4
Коммит b38eff8e4f
29 изменённых файлов: 3435 добавлений и 2731 удалений

Просмотреть файл

@ -1,3 +1,35 @@
20000401
- Big OpenBSD CVS update (mainly beginnings of SSH2 infrastructure)
- [auth.c session.c sshd.c auth.h]
split sshd.c -> auth.c session.c sshd.c plus cleanup and goto-removal
- [bufaux.c bufaux.h]
support ssh2 bignums
- [channels.c channels.h clientloop.c sshd.c nchan.c nchan.h packet.c]
[readconf.c ssh.c ssh.h serverloop.c]
replace big switch() with function tables (prepare for ssh2)
- [ssh2.h]
ssh2 message type codes
- [sshd.8]
reorder Xr to avoid cutting
- [serverloop.c]
close(fdin) if fdin != fdout, shutdown otherwise, ok theo@
- [channels.c]
missing close
allow bigger packets
- [cipher.c cipher.h]
support ssh2 ciphers
- [compress.c]
cleanup, less code
- [dispatch.c dispatch.h]
function tables for different message types
- [log-server.c]
do not log() if debuggin to stderr
rename a cpp symbol, to avoid param.h collision
- [mpaux.c]
KNF
- [nchan.c]
sync w/ channels.c
20000326
- Better tests for OpenSSL w/ RSAref
- Added replacement setenv() function from OpenBSD libc. Suggested by

Просмотреть файл

@ -31,11 +31,11 @@ LDFLAGS=-L. @LDFLAGS@
TARGETS=ssh sshd ssh-add ssh-keygen ssh-agent scp $(EXTRA_TARGETS)
LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o key.o log.o match.o mpaux.o nchan.o packet.o radix.o random.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
LIBOBJS= atomicio.o authfd.o authfile.o bsd-bindresvport.o bsd-daemon.o bsd-misc.o bsd-mktemp.o bsd-rresvport.o bsd-setenv.o bsd-snprintf.o bsd-strlcat.o bsd-strlcpy.o bufaux.o buffer.o canohost.o channels.o cipher.o compat.o compress.o crc32.o deattack.o dispatch.o fake-getaddrinfo.o fake-getnameinfo.o fingerprint.o hostfile.o key.o log.o match.o mpaux.o nchan.o packet.o radix.o random.o readpass.o rsa.o tildexpand.o ttymodes.o uidswap.o xmalloc.o
SSHOBJS= ssh.o sshconnect.o log-client.o readconf.o clientloop.o
SSHDOBJS= sshd.o auth-rhosts.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o serverloop.o bsd-login.o md5crypt.o
SSHDOBJS= sshd.o auth-rhosts.o auth-krb4.o auth-pam.o auth-passwd.o auth-rsa.o auth-rh-rsa.o pty.o log-server.o login.o servconf.o serverloop.o bsd-login.o md5crypt.o session.o auth.o
TROFFMAN = scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh.1 sshd.8
CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0

606
auth.c Normal file
Просмотреть файл

@ -0,0 +1,606 @@
/*
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
*/
#include "includes.h"
RCSID("$OpenBSD: auth.c,v 1.1 2000/03/28 21:15:45 markus Exp $");
#include "xmalloc.h"
#include "rsa.h"
#include "ssh.h"
#include "pty.h"
#include "packet.h"
#include "buffer.h"
#include "cipher.h"
#include "mpaux.h"
#include "servconf.h"
#include "channels.h"
#include "match.h"
#include "session.h"
#include "dispatch.h"
/* import */
extern ServerOptions options;
extern char *forced_command;
/*
* Check if the user is allowed to log in via ssh. If user is listed in
* DenyUsers or user's primary group is listed in DenyGroups, false will
* be returned. If AllowUsers isn't empty and user isn't listed there, or
* if AllowGroups isn't empty and user isn't listed there, false will be
* returned.
* If the user's shell is not executable, false will be returned.
* Otherwise true is returned.
*/
static int
allowed_user(struct passwd * pw)
{
struct stat st;
struct group *grp;
int i;
#ifdef WITH_AIXAUTHENTICATE
char *loginmsg;
#endif /* WITH_AIXAUTHENTICATE */
/* Shouldn't be called if pw is NULL, but better safe than sorry... */
if (!pw)
return 0;
/* deny if shell does not exists or is not executable */
if (stat(pw->pw_shell, &st) != 0)
return 0;
if (!((st.st_mode & S_IFREG) && (st.st_mode & (S_IXOTH|S_IXUSR|S_IXGRP))))
return 0;
/* Return false if user is listed in DenyUsers */
if (options.num_deny_users > 0) {
if (!pw->pw_name)
return 0;
for (i = 0; i < options.num_deny_users; i++)
if (match_pattern(pw->pw_name, options.deny_users[i]))
return 0;
}
/* Return false if AllowUsers isn't empty and user isn't listed there */
if (options.num_allow_users > 0) {
if (!pw->pw_name)
return 0;
for (i = 0; i < options.num_allow_users; i++)
if (match_pattern(pw->pw_name, options.allow_users[i]))
break;
/* i < options.num_allow_users iff we break for loop */
if (i >= options.num_allow_users)
return 0;
}
/* Get the primary group name if we need it. Return false if it fails */
if (options.num_deny_groups > 0 || options.num_allow_groups > 0) {
grp = getgrgid(pw->pw_gid);
if (!grp)
return 0;
/* Return false if user's group is listed in DenyGroups */
if (options.num_deny_groups > 0) {
if (!grp->gr_name)
return 0;
for (i = 0; i < options.num_deny_groups; i++)
if (match_pattern(grp->gr_name, options.deny_groups[i]))
return 0;
}
/*
* Return false if AllowGroups isn't empty and user's group
* isn't listed there
*/
if (options.num_allow_groups > 0) {
if (!grp->gr_name)
return 0;
for (i = 0; i < options.num_allow_groups; i++)
if (match_pattern(grp->gr_name, options.allow_groups[i]))
break;
/* i < options.num_allow_groups iff we break for
loop */
if (i >= options.num_allow_groups)
return 0;
}
}
#ifdef WITH_AIXAUTHENTICATE
if (loginrestrictions(pw->pw_name,S_LOGIN,NULL,&loginmsg) != 0)
return 0;
#endif /* WITH_AIXAUTHENTICATE */
/* We found no reason not to let this user try to log on... */
return 1;
}
/*
* convert ssh auth msg type into description
*/
char *
get_authname(int type)
{
static char buf[1024];
switch (type) {
case SSH_CMSG_AUTH_PASSWORD:
return "password";
case SSH_CMSG_AUTH_RSA:
return "rsa";
case SSH_CMSG_AUTH_RHOSTS_RSA:
return "rhosts-rsa";
case SSH_CMSG_AUTH_RHOSTS:
return "rhosts";
#ifdef KRB4
case SSH_CMSG_AUTH_KERBEROS:
return "kerberos";
#endif
#ifdef SKEY
case SSH_CMSG_AUTH_TIS_RESPONSE:
return "s/key";
#endif
}
snprintf(buf, sizeof buf, "bad-auth-msg-%d", type);
return buf;
}
#define AUTH_FAIL_MAX 6
#define AUTH_FAIL_LOG (AUTH_FAIL_MAX/2)
#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
/*
* The user does not exist or access is denied,
* but fake indication that authentication is needed.
*/
void
do_fake_authloop1(char *user)
{
int attempt = 0;
log("Faking authloop for illegal user %.200s from %.200s port %d",
user,
get_remote_ipaddr(),
get_remote_port());
#ifdef WITH_AIXAUTHENTICATE
if (strncmp(get_authname(type),"password",
strlen(get_authname(type))) == 0)
loginfailed(pw->pw_name,get_canonical_hostname(),"ssh");
#endif /* WITH_AIXAUTHENTICATE */
/* Indicate that authentication is needed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
/*
* Keep reading packets, and always respond with a failure. This is
* to avoid disclosing whether such a user really exists.
*/
for (attempt = 1;; attempt++) {
/* Read a packet. This will not return if the client disconnects. */
int plen;
#ifndef SKEY
(void)packet_read(&plen);
#else /* SKEY */
int type = packet_read(&plen);
unsigned int dlen;
char *password, *skeyinfo;
/* Try to send a fake s/key challenge. */
if (options.skey_authentication == 1 &&
(skeyinfo = skey_fake_keyinfo(user)) != NULL) {
password = NULL;
if (type == SSH_CMSG_AUTH_TIS) {
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
packet_put_string(skeyinfo, strlen(skeyinfo));
packet_send();
packet_write_wait();
continue;
} else if (type == SSH_CMSG_AUTH_PASSWORD &&
options.password_authentication &&
(password = packet_get_string(&dlen)) != NULL &&
dlen == 5 &&
strncasecmp(password, "s/key", 5) == 0 ) {
packet_send_debug(skeyinfo);
}
if (password != NULL)
xfree(password);
}
#endif
if (attempt > AUTH_FAIL_MAX)
packet_disconnect(AUTH_FAIL_MSG, user);
/*
* Send failure. This should be indistinguishable from a
* failed authentication.
*/
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
}
/* NOTREACHED */
abort();
}
/*
* read packets and try to authenticate local user *pw.
* return if authentication is successfull
*/
void
do_authloop(struct passwd * pw)
{
int attempt = 0;
unsigned int bits;
RSA *client_host_key;
BIGNUM *n;
char *client_user = NULL, *password = NULL;
char user[1024];
unsigned int dlen;
int plen, nlen, elen;
unsigned int ulen;
int type = 0;
void (*authlog) (const char *fmt,...) = verbose;
/* Indicate that authentication is needed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
for (attempt = 1;; attempt++) {
int authenticated = 0;
strlcpy(user, "", sizeof user);
/* Get a packet from the client. */
type = packet_read(&plen);
/* Process the packet. */
switch (type) {
#ifdef AFS
case SSH_CMSG_HAVE_KERBEROS_TGT:
if (!options.kerberos_tgt_passing) {
/* packet_get_all(); */
verbose("Kerberos tgt passing disabled.");
break;
} else {
/* Accept Kerberos 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);
xfree(tgt);
}
continue;
case SSH_CMSG_HAVE_AFS_TOKEN:
if (!options.afs_token_passing || !k_hasafs()) {
/* packet_get_all(); */
verbose("AFS token passing disabled.");
break;
} else {
/* Accept AFS token. */
char *token_string = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
if (!auth_afs_token(pw, token_string))
verbose("AFS token REFUSED for %s", pw->pw_name);
xfree(token_string);
}
continue;
#endif /* AFS */
#ifdef KRB4
case SSH_CMSG_AUTH_KERBEROS:
if (!options.kerberos_authentication) {
/* packet_get_all(); */
verbose("Kerberos authentication disabled.");
break;
} else {
/* Try Kerberos v4 authentication. */
KTEXT_ST auth;
char *tkt_user = NULL;
char *kdata = packet_get_string((unsigned int *) &auth.length);
packet_integrity_check(plen, 4 + auth.length, type);
if (auth.length < MAX_KTXT_LEN)
memcpy(auth.dat, kdata, auth.length);
xfree(kdata);
authenticated = auth_krb4(pw->pw_name, &auth, &tkt_user);
if (authenticated) {
snprintf(user, sizeof user, " tktuser %s", tkt_user);
xfree(tkt_user);
}
}
break;
#endif /* KRB4 */
case SSH_CMSG_AUTH_RHOSTS:
if (!options.rhosts_authentication) {
verbose("Rhosts authentication disabled.");
break;
}
/*
* Get client user name. Note that we just have to
* trust the client; this is one reason why rhosts
* authentication is insecure. (Another is
* IP-spoofing on a local network.)
*/
client_user = packet_get_string(&ulen);
packet_integrity_check(plen, 4 + ulen, type);
/* Try to authenticate using /etc/hosts.equiv and
.rhosts. */
authenticated = auth_rhosts(pw, client_user);
snprintf(user, sizeof user, " ruser %s", client_user);
break;
case SSH_CMSG_AUTH_RHOSTS_RSA:
if (!options.rhosts_rsa_authentication) {
verbose("Rhosts with RSA authentication disabled.");
break;
}
/*
* Get client user name. Note that we just have to
* trust the client; root on the client machine can
* claim to be any user.
*/
client_user = packet_get_string(&ulen);
/* Get the client host key. */
client_host_key = RSA_new();
if (client_host_key == NULL)
fatal("RSA_new failed");
client_host_key->e = BN_new();
client_host_key->n = BN_new();
if (client_host_key->e == NULL || client_host_key->n == NULL)
fatal("BN_new failed");
bits = packet_get_int();
packet_get_bignum(client_host_key->e, &elen);
packet_get_bignum(client_host_key->n, &nlen);
if (bits != BN_num_bits(client_host_key->n))
error("Warning: keysize mismatch for client_host_key: "
"actual %d, announced %d", BN_num_bits(client_host_key->n), bits);
packet_integrity_check(plen, (4 + ulen) + 4 + elen + nlen, type);
authenticated = auth_rhosts_rsa(pw, client_user, client_host_key);
RSA_free(client_host_key);
snprintf(user, sizeof user, " ruser %s", client_user);
break;
case SSH_CMSG_AUTH_RSA:
if (!options.rsa_authentication) {
verbose("RSA authentication disabled.");
break;
}
/* RSA authentication requested. */
n = BN_new();
packet_get_bignum(n, &nlen);
packet_integrity_check(plen, nlen, type);
authenticated = auth_rsa(pw, n);
BN_clear_free(n);
break;
case SSH_CMSG_AUTH_PASSWORD:
if (!options.password_authentication) {
verbose("Password authentication disabled.");
break;
}
/*
* Read user password. It is in plain text, but was
* transmitted over the encrypted channel so it is
* not visible to an outside observer.
*/
password = packet_get_string(&dlen);
packet_integrity_check(plen, 4 + dlen, type);
#ifdef USE_PAM
/* Do PAM auth with password */
authenticated = auth_pam_password(pw, password);
#else /* USE_PAM */
/* Try authentication with the password. */
authenticated = auth_password(pw, password);
#endif /* USE_PAM */
memset(password, 0, strlen(password));
xfree(password);
break;
#ifdef SKEY
case SSH_CMSG_AUTH_TIS:
debug("rcvd SSH_CMSG_AUTH_TIS");
if (options.skey_authentication == 1) {
char *skeyinfo = skey_keyinfo(pw->pw_name);
if (skeyinfo == NULL) {
debug("generating fake skeyinfo for %.100s.", pw->pw_name);
skeyinfo = skey_fake_keyinfo(pw->pw_name);
}
if (skeyinfo != NULL) {
/* we send our s/key- in tis-challenge messages */
debug("sending challenge '%s'", skeyinfo);
packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
packet_put_string(skeyinfo, strlen(skeyinfo));
packet_send();
packet_write_wait();
continue;
}
}
break;
case SSH_CMSG_AUTH_TIS_RESPONSE:
debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
if (options.skey_authentication == 1) {
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);
xfree(response);
}
break;
#else
case SSH_CMSG_AUTH_TIS:
/* TIS Authentication is unsupported */
log("TIS authentication unsupported.");
break;
#endif
default:
/*
* Any unknown messages will be ignored (and failure
* returned) during authentication.
*/
log("Unknown message during authentication: type %d", type);
break;
}
/*
* Check if the user is logging in as root and root logins
* are disallowed.
* Note that root login is allowed for forced commands.
*/
if (authenticated && pw->pw_uid == 0 && !options.permit_root_login) {
if (forced_command) {
log("Root login accepted for forced command.");
} else {
authenticated = 0;
log("ROOT LOGIN REFUSED FROM %.200s",
get_canonical_hostname());
}
}
/* Raise logging level */
if (authenticated ||
attempt == AUTH_FAIL_LOG ||
type == SSH_CMSG_AUTH_PASSWORD)
authlog = log;
authlog("%s %s for %.200s from %.200s port %d%s",
authenticated ? "Accepted" : "Failed",
get_authname(type),
pw->pw_uid == 0 ? "ROOT" : pw->pw_name,
get_remote_ipaddr(),
get_remote_port(),
user);
#ifdef USE_PAM
if (authenticated) {
if (!do_pam_account(pw->pw_name, client_user)) {
if (client_user != NULL) {
xfree(client_user);
client_user = NULL;
}
do_fake_authloop1(pw->pw_name);
}
return;
}
#else /* USE_PAM */
if (authenticated) {
return;
}
#endif /* USE_PAM */
if (client_user != NULL) {
xfree(client_user);
client_user = NULL;
}
if (attempt > AUTH_FAIL_MAX)
packet_disconnect(AUTH_FAIL_MSG, pw->pw_name);
/* Send a message indicating that the authentication attempt failed. */
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
}
}
/*
* Performs authentication of an incoming connection. Session key has already
* been exchanged and encryption is enabled.
*/
void
do_authentication()
{
struct passwd *pw, pwcopy;
int plen;
unsigned int ulen;
char *user;
#ifdef WITH_AIXAUTHENTICATE
char *loginmsg;
#endif /* WITH_AIXAUTHENTICATE */
/* Get the name of the user that we wish to log in as. */
packet_read_expect(&plen, SSH_CMSG_USER);
/* Get the user name. */
user = packet_get_string(&ulen);
packet_integrity_check(plen, (4 + ulen), SSH_CMSG_USER);
setproctitle("%s", user);
#ifdef AFS
/* If machine has AFS, set process authentication group. */
if (k_hasafs()) {
k_setpag();
k_unlog();
}
#endif /* AFS */
/* Verify that the user is a valid user. */
pw = getpwnam(user);
if (!pw || !allowed_user(pw))
do_fake_authloop1(user);
xfree(user);
/* Take a copy of the returned structure. */
memset(&pwcopy, 0, sizeof(pwcopy));
pwcopy.pw_name = xstrdup(pw->pw_name);
pwcopy.pw_passwd = xstrdup(pw->pw_passwd);
pwcopy.pw_uid = pw->pw_uid;
pwcopy.pw_gid = pw->pw_gid;
pwcopy.pw_dir = xstrdup(pw->pw_dir);
pwcopy.pw_shell = xstrdup(pw->pw_shell);
pw = &pwcopy;
#ifdef USE_PAM
start_pam(pw);
#endif
/*
* If we are not running as root, the user must have the same uid as
* the server.
*/
if (getuid() != 0 && pw->pw_uid != getuid())
packet_disconnect("Cannot change user when server not running as root.");
debug("Attempting authentication for %.100s.", pw->pw_name);
/* If the user has no password, accept authentication immediately. */
if (options.password_authentication &&
#ifdef KRB4
(!options.kerberos_authentication || options.kerberos_or_local_passwd) &&
#endif /* KRB4 */
#ifdef USE_PAM
auth_pam_password(pw, "")) {
#else /* USE_PAM */
auth_password(pw, "")) {
#endif /* USE_PAM */
/* Authentication with empty password succeeded. */
log("Login for user %s from %.100s, accepted without authentication.",
pw->pw_name, get_remote_ipaddr());
} else {
/* Loop until the user has been authenticated or the
connection is closed, do_authloop() returns only if
authentication is successfull */
do_authloop(pw);
}
/* The user has been authenticated and accepted. */
#ifdef WITH_AIXAUTHENTICATE
loginsuccess(user,get_canonical_hostname(),"ssh",&loginmsg);
#endif /* WITH_AIXAUTHENTICATE */
packet_start(SSH_SMSG_SUCCESS);
packet_send();
packet_write_wait();
/* Perform session preparation. */
do_authenticated(pw);
}

6
auth.h Normal file
Просмотреть файл

@ -0,0 +1,6 @@
#ifndef AUTH_H
#define AUTH_H
void do_authentication(void);
#endif

Просмотреть файл

@ -12,10 +12,12 @@
* Auxiliary functions for storing and retrieving various data types to/from
* Buffers.
*
* SSH2 packet format added by Markus Friedl
*
*/
#include "includes.h"
RCSID("$Id: bufaux.c,v 1.8 2000/03/17 12:40:15 damien Exp $");
RCSID("$Id: bufaux.c,v 1.9 2000/04/01 01:09:23 damien Exp $");
#include "ssh.h"
@ -82,6 +84,50 @@ 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).
*/
@ -142,6 +188,11 @@ 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).

Просмотреть файл

@ -11,7 +11,7 @@
*
*/
/* RCSID("$Id: bufaux.h,v 1.3 1999/11/25 00:54:58 damien Exp $"); */
/* RCSID("$Id: bufaux.h,v 1.4 2000/04/01 01:09:23 damien Exp $"); */
#ifndef BUFAUX_H
#define BUFAUX_H
@ -23,9 +23,11 @@
* by (bits+7)/8 bytes of binary data, msb first.
*/
void buffer_put_bignum(Buffer * buffer, BIGNUM * value);
void buffer_put_bignum2(Buffer * buffer, BIGNUM * value);
/* Retrieves an BIGNUM from the buffer. */
int buffer_get_bignum(Buffer * buffer, BIGNUM * value);
int buffer_get_bignum2(Buffer *buffer, BIGNUM * value);
/* Returns an integer from the buffer (4 bytes, msb first). */
unsigned int buffer_get_int(Buffer * buffer);
@ -51,5 +53,6 @@ char *buffer_get_string(Buffer * buffer, unsigned int *length_ptr);
/* Stores and arbitrary binary string in the buffer. */
void buffer_put_string(Buffer * buffer, const void *buf, unsigned int len);
void buffer_put_cstring(Buffer *buffer, const char *s);
#endif /* BUFAUX_H */

1244
channels.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,4 +1,4 @@
/* RCSID("$Id: channels.h,v 1.4 1999/11/25 00:54:58 damien Exp $"); */
/* RCSID("$Id: channels.h,v 1.5 2000/04/01 01:09:23 damien Exp $"); */
#ifndef CHANNELS_H
#define CHANNELS_H
@ -10,17 +10,18 @@
#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
/* SSH_CHANNEL_AUTH_FD 6 authentication fd */
#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */
#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */
#define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */
#define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
#define SSH_CHANNEL_LARVAL 10 /* larval session */
#define SSH_CHANNEL_MAX_TYPE 11
/*
* Data structure for channel data. This is iniailized in channel_allocate
* and cleared in channel_free.
*/
typedef void channel_callback_fn(int id, void *arg);
typedef struct Channel {
int type; /* channel type/state */
@ -29,15 +30,192 @@ typedef struct Channel {
/* peer can be reached over encrypted connection, via packet-sent */
int istate; /* input from channel (state of receive half) */
int ostate; /* output to channel (state of transmit half) */
int sock; /* data socket, linked to this channel */
int rfd; /* read fd */
int wfd; /* write fd */
int efd; /* extended fd */
int sock; /* sock fd */
Buffer input; /* data read from socket, to be sent over
* encrypted connection */
Buffer output; /* data received over encrypted connection for
* send on socket */
Buffer extended;
char path[200]; /* path for unix domain sockets, or host name
* for forwards */
int listening_port; /* port being listened for forwards */
int host_port; /* remote port to connect for forwards */
char *remote_name; /* remote hostname */
int remote_window;
int remote_maxpacket;
int local_window;
int local_window_max;
int local_consumed;
int local_maxpacket;
int extended_usage;
char *ctype; /* type */
// callback
channel_callback_fn *cb_fn;
void *cb_arg;
int cb_event;
channel_callback_fn *dettach_user;
} Channel;
#define CHAN_EXTENDED_IGNORE 0
#define CHAN_EXTENDED_READ 1
#define CHAN_EXTENDED_WRITE 2
void channel_open(int id);
Channel *channel_lookup(int id);
int
channel_new(char *ctype, int type, int rfd, int wfd, int efd,
int window, int maxpack, int extended_usage, char *remote_name);
void channel_input_close(int type, int plen);
void channel_input_close_confirmation(int type, int plen);
void channel_input_data(int type, int plen);
void channel_input_ieof(int type, int plen);
void channel_input_oclose(int type, int plen);
void channel_input_open_confirmation(int type, int plen);
void channel_input_open_failure(int type, int plen);
void channel_input_port_open(int type, int plen);
void channel_input_open(int type, int plen);
/* 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);
/* Returns true if no channel has too much buffered data. */
int channel_not_very_much_buffered_data(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);
/*
* 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 type, int plen);
/*
* 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(int type, int plen);
#endif

123
cipher.c
Просмотреть файл

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$Id: cipher.c,v 1.14 2000/03/26 03:04:52 damien Exp $");
RCSID("$Id: cipher.c,v 1.15 2000/04/01 01:09:23 damien Exp $");
#include "ssh.h"
#include "cipher.h"
@ -122,7 +122,12 @@ static char *cipher_names[] =
"3des",
"tss",
"rc4",
"blowfish"
"blowfish",
"reserved",
"blowfish-cbc",
"3des-cbc",
"arcfour",
"cast128-cbc"
};
/*
@ -137,6 +142,10 @@ cipher_mask()
unsigned int mask = 0;
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
mask |= 1 << SSH_CIPHER_BLOWFISH;
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;
}
@ -233,16 +242,84 @@ 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
@ -272,6 +349,27 @@ cipher_encrypt(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_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));
}
@ -306,6 +404,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));
}

Просмотреть файл

@ -11,7 +11,7 @@
*
*/
/* RCSID("$Id: cipher.h,v 1.6 2000/03/26 03:04:52 damien Exp $"); */
/* RCSID("$Id: cipher.h,v 1.7 2000/04/01 01:09:23 damien Exp $"); */
#ifndef CIPHER_H
#define CIPHER_H
@ -21,10 +21,14 @@
#ifdef HAVE_OPENSSL
#include <openssl/des.h>
#include <openssl/blowfish.h>
#include <openssl/rc4.h>
#include <openssl/cast.h>
#endif
#ifdef HAVE_SSL
#include <ssl/des.h>
#include <ssl/blowfish.h>
#include <ssl/rc4.h>
#include <ssl/cast.h>
#endif
/* Cipher types. New types can be added, but old types should not be removed
@ -37,6 +41,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;
@ -52,6 +63,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;
/*
@ -77,6 +93,10 @@ int cipher_number(const char *name);
void
cipher_set_key(CipherContext * context, int cipher,
const unsigned char *key, int keylen, int for_encryption);
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,

Просмотреть файл

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: clientloop.c,v 1.7 1999/12/07 04:38:32 damien Exp $");
RCSID("$Id: clientloop.c,v 1.8 2000/04/01 01:09:23 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -24,6 +24,11 @@ RCSID("$Id: clientloop.c,v 1.7 1999/12/07 04:38:32 damien Exp $");
#include "authfd.h"
#include "readconf.h"
#include "compat.h"
#include "channels.h"
#include "dispatch.h"
/* Flag indicating that stdin should be redirected from /dev/null. */
extern int stdin_null_flag;
@ -228,108 +233,6 @@ client_check_initial_eof_on_stdin()
}
}
/*
* Get packets from the connection input buffer, and process them as long as
* there are packets available.
*/
void
client_process_buffered_input_packets()
{
int type;
char *data;
unsigned int data_len;
int payload_len;
/* Process any buffered packets from the server. */
while (!quit_pending &&
(type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
switch (type) {
case SSH_SMSG_STDOUT_DATA:
data = packet_get_string(&data_len);
packet_integrity_check(payload_len, 4 + data_len, type);
buffer_append(&stdout_buffer, data, data_len);
stdout_bytes += data_len;
memset(data, 0, data_len);
xfree(data);
break;
case SSH_SMSG_STDERR_DATA:
data = packet_get_string(&data_len);
packet_integrity_check(payload_len, 4 + data_len, type);
buffer_append(&stderr_buffer, data, data_len);
stdout_bytes += data_len;
memset(data, 0, data_len);
xfree(data);
break;
case SSH_SMSG_EXITSTATUS:
packet_integrity_check(payload_len, 4, type);
exit_status = packet_get_int();
/* Acknowledge the exit. */
packet_start(SSH_CMSG_EXIT_CONFIRMATION);
packet_send();
/*
* Must wait for packet to be sent since we are
* exiting the loop.
*/
packet_write_wait();
/* Flag that we want to exit. */
quit_pending = 1;
break;
case SSH_SMSG_X11_OPEN:
x11_input_open(payload_len);
break;
case SSH_MSG_PORT_OPEN:
channel_input_port_open(payload_len);
break;
case SSH_SMSG_AGENT_OPEN:
packet_integrity_check(payload_len, 4, type);
auth_input_open_request();
break;
case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
packet_integrity_check(payload_len, 4 + 4, type);
channel_input_open_confirmation();
break;
case SSH_MSG_CHANNEL_OPEN_FAILURE:
packet_integrity_check(payload_len, 4, type);
channel_input_open_failure();
break;
case SSH_MSG_CHANNEL_DATA:
channel_input_data(payload_len);
break;
case SSH_MSG_CHANNEL_CLOSE:
packet_integrity_check(payload_len, 4, type);
channel_input_close();
break;
case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
packet_integrity_check(payload_len, 4, type);
channel_input_close_confirmation();
break;
default:
/*
* Any unknown packets received during the actual
* session cause the session to terminate. This is
* intended to make debugging easier since no
* confirmations are sent. Any compatible protocol
* extensions must be negotiated during the
* preparatory phase.
*/
packet_disconnect("Protocol error during session: type %d",
type);
}
}
}
/*
* Make packets from buffered stdin data, and buffer them for sending to the
@ -775,6 +678,24 @@ client_process_output(fd_set * writeset)
}
}
/*
* Get packets from the connection input buffer, and process them as long as
* there are packets available.
*
* Any unknown packets received during the actual
* session cause the session to terminate. This is
* intended to make debugging easier since no
* confirmations are sent. Any compatible protocol
* extensions must be negotiated during the
* preparatory phase.
*/
void
client_process_buffered_input_packets()
{
dispatch_run(DISPATCH_NONBLOCK, &quit_pending);
}
/*
* Implements the interactive session with the server. This is called after
* the user has been authenticated, and a command has been started on the
@ -782,6 +703,8 @@ client_process_output(fd_set * writeset)
* character for terminating or suspending the session.
*/
void client_init_dispatch(void);
int
client_loop(int have_pty, int escape_char_arg)
{
@ -816,6 +739,8 @@ client_loop(int have_pty, int escape_char_arg)
buffer_init(&stdout_buffer);
buffer_init(&stderr_buffer);
client_init_dispatch();
/* Set signal handlers to restore non-blocking mode. */
signal(SIGINT, signal_handler);
signal(SIGQUIT, signal_handler);
@ -950,3 +875,77 @@ client_loop(int have_pty, int escape_char_arg)
debug("Exit status %d", exit_status);
return exit_status;
}
/*********/
void
client_input_stdout_data(int type, int plen)
{
unsigned int data_len;
char *data = packet_get_string(&data_len);
packet_integrity_check(plen, 4 + data_len, type);
buffer_append(&stdout_buffer, data, data_len);
stdout_bytes += data_len;
memset(data, 0, data_len);
xfree(data);
}
void
client_input_stderr_data(int type, int plen)
{
unsigned int data_len;
char *data = packet_get_string(&data_len);
packet_integrity_check(plen, 4 + data_len, type);
buffer_append(&stderr_buffer, data, data_len);
stdout_bytes += data_len;
memset(data, 0, data_len);
xfree(data);
}
void
client_input_exit_status(int type, int plen)
{
packet_integrity_check(plen, 4, type);
exit_status = packet_get_int();
/* Acknowledge the exit. */
packet_start(SSH_CMSG_EXIT_CONFIRMATION);
packet_send();
/*
* Must wait for packet to be sent since we are
* exiting the loop.
*/
packet_write_wait();
/* Flag that we want to exit. */
quit_pending = 1;
}
void
client_init_dispatch_13()
{
dispatch_init(NULL);
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
dispatch_set(SSH_SMSG_AGENT_OPEN, &auth_input_open_request);
dispatch_set(SSH_SMSG_EXITSTATUS, &client_input_exit_status);
dispatch_set(SSH_SMSG_STDERR_DATA, &client_input_stderr_data);
dispatch_set(SSH_SMSG_STDOUT_DATA, &client_input_stdout_data);
dispatch_set(SSH_SMSG_X11_OPEN, &x11_input_open);
}
void
client_init_dispatch_15()
{
client_init_dispatch_13();
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, & channel_input_oclose);
}
void
client_init_dispatch()
{
if (compat13)
client_init_dispatch_13();
else
client_init_dispatch_15();
}

Просмотреть файл

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: compress.c,v 1.4 2000/03/17 12:40:16 damien Exp $");
RCSID("$Id: compress.c,v 1.5 2000/04/01 01:09:24 damien Exp $");
#include "ssh.h"
#include "buffer.h"
@ -90,23 +90,13 @@ buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
case Z_OK:
/* Append compressed data to output_buffer. */
buffer_append(output_buffer, buf,
sizeof(buf) - outgoing_stream.avail_out);
sizeof(buf) - outgoing_stream.avail_out);
break;
case Z_STREAM_END:
fatal("buffer_compress: deflate returned Z_STREAM_END");
/* NOTREACHED */
case Z_STREAM_ERROR:
fatal("buffer_compress: deflate returned Z_STREAM_ERROR");
/* NOTREACHED */
case Z_BUF_ERROR:
fatal("buffer_compress: deflate returned Z_BUF_ERROR");
/* NOTREACHED */
default:
fatal("buffer_compress: deflate returned %d", status);
/* NOTREACHED */
}
}
while (outgoing_stream.avail_out == 0);
} while (outgoing_stream.avail_out == 0);
}
/*
@ -127,27 +117,17 @@ buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
incoming_stream.next_in = (unsigned char *) buffer_ptr(input_buffer);
incoming_stream.avail_in = buffer_len(input_buffer);
incoming_stream.next_out = (unsigned char *) buf;
incoming_stream.avail_out = sizeof(buf);
for (;;) {
/* Set up fixed-size output buffer. */
incoming_stream.next_out = (unsigned char *) buf;
incoming_stream.avail_out = sizeof(buf);
status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
switch (status) {
case Z_OK:
buffer_append(output_buffer, buf,
sizeof(buf) - incoming_stream.avail_out);
incoming_stream.next_out = (unsigned char *) buf;
incoming_stream.avail_out = sizeof(buf);
sizeof(buf) - incoming_stream.avail_out);
break;
case Z_STREAM_END:
fatal("buffer_uncompress: inflate returned Z_STREAM_END");
/* NOTREACHED */
case Z_DATA_ERROR:
fatal("buffer_uncompress: inflate returned Z_DATA_ERROR");
/* NOTREACHED */
case Z_STREAM_ERROR:
fatal("buffer_uncompress: inflate returned Z_STREAM_ERROR");
/* NOTREACHED */
case Z_BUF_ERROR:
/*
* Comments in zlib.h say that we should keep calling
@ -155,11 +135,9 @@ buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
* be the error that we get.
*/
return;
case Z_MEM_ERROR:
fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");
/* NOTREACHED */
default:
fatal("buffer_uncompress: inflate returned %d", status);
/* NOTREACHED */
}
}
}

78
dispatch.c Normal file
Просмотреть файл

@ -0,0 +1,78 @@
/*
* Copyright (c) 2000 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Markus Friedl.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$Id: dispatch.c,v 1.1 2000/04/01 01:09:24 damien Exp $");
#include "ssh.h"
#include "dispatch.h"
#include "packet.h"
#define DISPATCH_MIN 0
#define DISPATCH_MAX 255
dispatch_fn *dispatch[DISPATCH_MAX];
void
dispatch_protocol_error(int type, int plen)
{
error("Hm, dispatch protocol error: type %d plen %d", type, plen);
}
void
dispatch_init(dispatch_fn *dflt)
{
int i;
for (i = 0; i < DISPATCH_MAX; i++)
dispatch[i] = dflt;
}
void
dispatch_set(int type, dispatch_fn *fn)
{
dispatch[type] = fn;
}
void
dispatch_run(int mode, int *done)
{
for (;;) {
int plen;
int type;
if (mode == DISPATCH_BLOCK) {
type = packet_read(&plen);
} else {
type = packet_read_poll(&plen);
if (type == SSH_MSG_NONE)
return;
}
if (type > 0 && type < DISPATCH_MAX && dispatch[type] != NULL)
(*dispatch[type])(type, plen);
else
packet_disconnect("protocol error: rcvd type %d", type);
if (done != NULL && *done)
return;
}
}

11
dispatch.h Normal file
Просмотреть файл

@ -0,0 +1,11 @@
enum {
DISPATCH_BLOCK,
DISPATCH_NONBLOCK
};
typedef void dispatch_fn(int type, int plen);
void dispatch_init(dispatch_fn *dflt);
void dispatch_set(int type, dispatch_fn *fn);
void dispatch_run(int mode, int *done);
void dispatch_protocol_error(int type, int plen);

Просмотреть файл

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: log-server.c,v 1.7 2000/03/09 10:27:50 damien Exp $");
RCSID("$Id: log-server.c,v 1.8 2000/04/01 01:09:24 damien Exp $");
#include <syslog.h>
#include "packet.h"
@ -137,9 +137,11 @@ do_log(LogLevel level, const char *fmt, va_list args)
} else {
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
}
if (log_on_stderr)
if (log_on_stderr) {
fprintf(stderr, "%s\n", msgbuf);
openlog(__progname, LOG_PID, log_facility);
syslog(pri, "%.500s", msgbuf);
closelog();
} else {
openlog(__progname, LOG_PID, log_facility);
syslog(pri, "%.500s", msgbuf);
closelog();
}
}

Просмотреть файл

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: mpaux.c,v 1.8 1999/12/13 23:47:16 damien Exp $");
RCSID("$Id: mpaux.c,v 1.9 2000/04/01 01:09:24 damien Exp $");
#include "getput.h"
#include "xmalloc.h"
@ -31,9 +31,9 @@ RCSID("$Id: mpaux.c,v 1.8 1999/12/13 23:47:16 damien 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);

Просмотреть файл

@ -28,7 +28,7 @@
*/
#include "includes.h"
RCSID("$Id: nchan.c,v 1.5 2000/01/14 04:45:50 damien Exp $");
RCSID("$Id: nchan.c,v 1.6 2000/04/01 01:09:24 damien Exp $");
#include "ssh.h"
@ -41,7 +41,6 @@ static void chan_send_ieof(Channel *c);
static void chan_send_oclose(Channel *c);
static void chan_shutdown_write(Channel *c);
static void chan_shutdown_read(Channel *c);
static void chan_delete_if_full_closed(Channel *c);
/*
* EVENTS update channel input/output states execute ACTIONS
@ -73,7 +72,6 @@ chan_rcvd_oclose(Channel *c)
error("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
return;
}
chan_delete_if_full_closed(c);
}
void
chan_read_failed(Channel *c)
@ -121,7 +119,6 @@ chan_rcvd_ieof(Channel *c)
case CHAN_OUTPUT_WAIT_IEOF:
debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
c->ostate = CHAN_OUTPUT_CLOSED;
chan_delete_if_full_closed(c);
break;
default:
error("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
@ -141,7 +138,6 @@ chan_write_failed(Channel *c)
debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
chan_send_oclose(c);
c->ostate = CHAN_OUTPUT_CLOSED;
chan_delete_if_full_closed(c);
break;
default:
error("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
@ -160,7 +156,6 @@ chan_obuf_empty(Channel *c)
debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
chan_send_oclose(c);
c->ostate = CHAN_OUTPUT_CLOSED;
chan_delete_if_full_closed(c);
break;
default:
error("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
@ -222,7 +217,7 @@ chan_shutdown_read(Channel *c)
error("chan_shutdown_read failed for #%d/fd%d [i%d o%d]: %.100s",
c->self, c->sock, c->istate, c->ostate, strerror(errno));
}
static void
void
chan_delete_if_full_closed(Channel *c)
{
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {

Просмотреть файл

@ -27,7 +27,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* RCSID("$Id: nchan.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */
/* RCSID("$Id: nchan.h,v 1.4 2000/04/01 01:09:24 damien Exp $"); */
#ifndef NCHAN_H
#define NCHAN_H
@ -83,4 +83,6 @@ void chan_write_failed(Channel * c);
void chan_obuf_empty(Channel * c);
void chan_init_iostates(Channel * c);
void chan_delete_if_full_closed(Channel *c);
#endif

Просмотреть файл

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: packet.c,v 1.12 2000/03/09 10:27:50 damien Exp $");
RCSID("$Id: packet.c,v 1.13 2000/04/01 01:09:25 damien Exp $");
#include "xmalloc.h"
#include "buffer.h"
@ -28,6 +28,7 @@ RCSID("$Id: packet.c,v 1.12 2000/03/09 10:27:50 damien Exp $");
#include "compress.h"
#include "deattack.h"
#include "channels.h"
/*
* This variable contains the file descriptors used for communicating with

4
pty.h
Просмотреть файл

@ -13,7 +13,7 @@
* tty.
*/
/* RCSID("$Id: pty.h,v 1.6 2000/03/09 10:27:51 damien Exp $"); */
/* RCSID("$Id: pty.h,v 1.7 2000/04/01 01:09:25 damien Exp $"); */
#ifndef PTY_H
#define PTY_H
@ -45,6 +45,4 @@ pty_change_window_size(int ptyfd, int row, int col,
void pty_setowner(struct passwd *pw, const char *ttyname);
void pty_setowner(struct passwd *pw, const char *ttyname);
#endif /* PTY_H */

Просмотреть файл

@ -14,11 +14,12 @@
*/
#include "includes.h"
RCSID("$Id: readconf.c,v 1.8 2000/03/09 10:27:51 damien Exp $");
RCSID("$Id: readconf.c,v 1.9 2000/04/01 01:09:25 damien Exp $");
#include "ssh.h"
#include "cipher.h"
#include "readconf.h"
#include "match.h"
#include "xmalloc.h"
/* Format of the configuration file:

Просмотреть файл

@ -13,6 +13,10 @@
#include "buffer.h"
#include "servconf.h"
#include "pty.h"
#include "channels.h"
#include "compat.h"
#include "dispatch.h"
static Buffer stdin_buffer; /* Buffer for stdin data. */
static Buffer stdout_buffer; /* Buffer for stdout data. */
@ -47,6 +51,8 @@ static volatile int child_terminated; /* The child has terminated. */
static volatile int child_has_selected; /* Child has had chance to drain. */
static volatile int child_wait_status; /* Status from wait(). */
void server_init_dispatch(void);
void
sigchld_handler(int sig)
{
@ -67,104 +73,6 @@ sigchld_handler(int sig)
errno = save_errno;
}
/*
* Process any buffered packets that have been received from the client.
*/
void
process_buffered_input_packets()
{
int type;
char *data;
unsigned int data_len;
int row, col, xpixel, ypixel;
int payload_len;
/* Process buffered packets from the client. */
while ((type = packet_read_poll(&payload_len)) != SSH_MSG_NONE) {
switch (type) {
case SSH_CMSG_STDIN_DATA:
/* Stdin data from the client. Append it to the buffer. */
/* Ignore any data if the client has closed stdin. */
if (fdin == -1)
break;
data = packet_get_string(&data_len);
packet_integrity_check(payload_len, (4 + data_len), type);
buffer_append(&stdin_buffer, data, data_len);
memset(data, 0, data_len);
xfree(data);
break;
case SSH_CMSG_EOF:
/*
* Eof from the client. The stdin descriptor to the
* program will be closed when all buffered data has
* drained.
*/
debug("EOF received for stdin.");
packet_integrity_check(payload_len, 0, type);
stdin_eof = 1;
break;
case SSH_CMSG_WINDOW_SIZE:
debug("Window change received.");
packet_integrity_check(payload_len, 4 * 4, type);
row = packet_get_int();
col = packet_get_int();
xpixel = packet_get_int();
ypixel = packet_get_int();
if (fdin != -1)
pty_change_window_size(fdin, row, col, xpixel, ypixel);
break;
case SSH_MSG_PORT_OPEN:
debug("Received port open request.");
channel_input_port_open(payload_len);
break;
case SSH_MSG_CHANNEL_OPEN_CONFIRMATION:
debug("Received channel open confirmation.");
packet_integrity_check(payload_len, 4 + 4, type);
channel_input_open_confirmation();
break;
case SSH_MSG_CHANNEL_OPEN_FAILURE:
debug("Received channel open failure.");
packet_integrity_check(payload_len, 4, type);
channel_input_open_failure();
break;
case SSH_MSG_CHANNEL_DATA:
channel_input_data(payload_len);
break;
case SSH_MSG_CHANNEL_CLOSE:
debug("Received channel close.");
packet_integrity_check(payload_len, 4, type);
channel_input_close();
break;
case SSH_MSG_CHANNEL_CLOSE_CONFIRMATION:
debug("Received channel close confirmation.");
packet_integrity_check(payload_len, 4, type);
channel_input_close_confirmation();
break;
default:
/*
* In this phase, any unexpected messages cause a
* protocol error. This is to ease debugging; also,
* since no confirmations are sent messages,
* unprocessed unknown messages could cause strange
* problems. Any compatible protocol extensions must
* be negotiated before entering the interactive
* session.
*/
packet_disconnect("Protocol error during session: type %d",
type);
}
}
}
/*
* Make packets from buffered stderr data, and buffer it for sending
* to the client.
@ -378,7 +286,7 @@ process_output(fd_set * writeset)
#ifdef USE_PIPES
close(fdin);
#else
if (fdout == -1)
if (fdin != fdout)
close(fdin);
else
shutdown(fdin, SHUT_WR); /* We will no longer send. */
@ -425,6 +333,12 @@ drain_output()
packet_write_wait();
}
void
process_buffered_input_packets()
{
dispatch_run(DISPATCH_NONBLOCK, NULL);
}
/*
* Performs the interactive session. This handles data transmission between
* the client and the program. Note that the notion of stdin, stdout, and
@ -490,6 +404,8 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
if (fderr == -1)
fderr_eof = 1;
server_init_dispatch();
/* Main loop of the server for the interactive session mode. */
for (;;) {
fd_set readset, writeset;
@ -505,7 +421,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
#ifdef USE_PIPES
close(fdin);
#else
if (fdout == -1)
if (fdin != fdout)
close(fdin);
else
shutdown(fdin, SHUT_WR); /* We will no longer send. */
@ -549,7 +465,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
(buffer_len(&stdout_buffer) == 0) &&
(buffer_len(&stderr_buffer) == 0)) {
if (!channel_still_open())
goto quit;
break;
if (!waiting_termination) {
const char *s = "Waiting for forwarded connections to terminate...\r\n";
char *cp;
@ -576,7 +492,6 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
process_output(&writeset);
}
quit:
/* Cleanup and termination code. */
/* Wait until all output has been sent to the client. */
@ -662,3 +577,79 @@ quit:
packet_disconnect("wait returned status %04x.", wait_status);
/* NOTREACHED */
}
void
server_input_stdin_data(int type, int plen)
{
char *data;
unsigned int data_len;
/* Stdin data from the client. Append it to the buffer. */
/* Ignore any data if the client has closed stdin. */
if (fdin == -1)
return;
data = packet_get_string(&data_len);
packet_integrity_check(plen, (4 + data_len), type);
buffer_append(&stdin_buffer, data, data_len);
memset(data, 0, data_len);
xfree(data);
}
void
server_input_eof(int type, int plen)
{
/*
* Eof from the client. The stdin descriptor to the
* program will be closed when all buffered data has
* drained.
*/
debug("EOF received for stdin.");
packet_integrity_check(plen, 0, type);
stdin_eof = 1;
}
void
server_input_window_size(int type, int plen)
{
int row = packet_get_int();
int col = packet_get_int();
int xpixel = packet_get_int();
int ypixel = packet_get_int();
debug("Window change received.");
packet_integrity_check(plen, 4 * 4, type);
if (fdin != -1)
pty_change_window_size(fdin, row, col, xpixel, ypixel);
}
void
server_init_dispatch_13()
{
debug("server_init_dispatch_13");
dispatch_init(NULL);
dispatch_set(SSH_CMSG_EOF, &server_input_eof);
dispatch_set(SSH_CMSG_STDIN_DATA, &server_input_stdin_data);
dispatch_set(SSH_CMSG_WINDOW_SIZE, &server_input_window_size);
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_close);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_close_confirmation);
dispatch_set(SSH_MSG_CHANNEL_DATA, &channel_input_data);
dispatch_set(SSH_MSG_CHANNEL_OPEN_CONFIRMATION, &channel_input_open_confirmation);
dispatch_set(SSH_MSG_CHANNEL_OPEN_FAILURE, &channel_input_open_failure);
dispatch_set(SSH_MSG_PORT_OPEN, &channel_input_port_open);
}
void
server_init_dispatch_15()
{
server_init_dispatch_13();
debug("server_init_dispatch_15");
dispatch_set(SSH_MSG_CHANNEL_CLOSE, &channel_input_ieof);
dispatch_set(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION, &channel_input_oclose);
}
void
server_init_dispatch()
{
if (compat13)
server_init_dispatch_13();
else
server_init_dispatch_15();
}

1153
session.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

7
session.h Normal file
Просмотреть файл

@ -0,0 +1,7 @@
#ifndef SESSION_H
#define SESSION_H
/* SSH1 */
void do_authenticated(struct passwd * pw);
#endif

3
ssh.c
Просмотреть файл

@ -11,7 +11,7 @@
*/
#include "includes.h"
RCSID("$Id: ssh.c,v 1.22 2000/03/26 03:04:54 damien Exp $");
RCSID("$Id: ssh.c,v 1.23 2000/04/01 01:09:26 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -20,6 +20,7 @@ RCSID("$Id: ssh.c,v 1.22 2000/03/26 03:04:54 damien Exp $");
#include "authfd.h"
#include "readconf.h"
#include "uidswap.h"
#include "channels.h"
#ifdef HAVE___PROGNAME
extern char *__progname;

171
ssh.h
Просмотреть файл

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: ssh.h,v 1.28 2000/03/26 03:04:54 damien Exp $"); */
/* RCSID("$Id: ssh.h,v 1.29 2000/04/01 01:09:26 damien Exp $"); */
#ifndef SSH_H
#define SSH_H
@ -486,175 +486,6 @@ 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);
/*
* Expands tildes in the file name. Returns data allocated by xmalloc.
* Warning: this calls getpw*.

106
ssh2.h Normal file
Просмотреть файл

@ -0,0 +1,106 @@
/*
* draft-ietf-secsh-architecture-04.txt
*
* Transport layer protocol:
*
* 1-19 Transport layer generic (e.g. disconnect, ignore, debug,
* etc)
* 20-29 Algorithm negotiation
* 30-49 Key exchange method specific (numbers can be reused for
* different authentication methods)
*
* User authentication protocol:
*
* 50-59 User authentication generic
* 60-79 User authentication method specific (numbers can be reused
* for different authentication methods)
*
* Connection protocol:
*
* 80-89 Connection protocol generic
* 90-127 Channel related messages
*
* Reserved for client protocols:
*
* 128-191 Reserved
*
* Local extensions:
*
* 192-255 Local extensions
*/
/* transport layer: generic */
#define SSH2_MSG_DISCONNECT 1
#define SSH2_MSG_IGNORE 2
#define SSH2_MSG_UNIMPLEMENTED 3
#define SSH2_MSG_DEBUG 4
#define SSH2_MSG_SERVICE_REQUEST 5
#define SSH2_MSG_SERVICE_ACCEPT 6
/* transport layer: alg negotiation */
#define SSH2_MSG_KEXINIT 20
#define SSH2_MSG_NEWKEYS 21
/* transport layer: kex specific messages, can be reused */
#define SSH2_MSG_KEXDH_INIT 30
#define SSH2_MSG_KEXDH_REPLY 31
/* user authentication: generic */
#define SSH2_MSG_USERAUTH_REQUEST 50
#define SSH2_MSG_USERAUTH_FAILURE 51
#define SSH2_MSG_USERAUTH_SUCCESS 52
#define SSH2_MSG_USERAUTH_BANNER 53
/* user authentication: method specific, can be reused */
#define SSH2_MSG_USERAUTH_PK_OK 60
#define SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ 60
#define SSH2_MSG_USERAUTH_INFO_REQUEST 60
#define SSH2_MSG_USERAUTH_INFO_RESPONSE 61
/* connection protocol: generic */
#define SSH2_MSG_GLOBAL_REQUEST 80
#define SSH2_MSG_REQUEST_SUCCESS 81
#define SSH2_MSG_REQUEST_FAILURE 82
/* channel related messages */
#define SSH2_MSG_CHANNEL_OPEN 90
#define SSH2_MSG_CHANNEL_OPEN_CONFIRMATION 91
#define SSH2_MSG_CHANNEL_OPEN_FAILURE 92
#define SSH2_MSG_CHANNEL_WINDOW_ADJUST 93
#define SSH2_MSG_CHANNEL_DATA 94
#define SSH2_MSG_CHANNEL_EXTENDED_DATA 95
#define SSH2_MSG_CHANNEL_EOF 96
#define SSH2_MSG_CHANNEL_CLOSE 97
#define SSH2_MSG_CHANNEL_REQUEST 98
#define SSH2_MSG_CHANNEL_SUCCESS 99
#define SSH2_MSG_CHANNEL_FAILURE 100
/* disconnect reason code */
#define SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1
#define SSH2_DISCONNECT_PROTOCOL_ERROR 2
#define SSH2_DISCONNECT_KEY_EXCHANGE_FAILED 3
#define SSH2_DISCONNECT_HOST_AUTHENTICATION_FAILED 4
#define SSH2_DISCONNECT_MAC_ERROR 5
#define SSH2_DISCONNECT_COMPRESSION_ERROR 6
#define SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE 7
#define SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED 8
#define SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE 9
#define SSH2_DISCONNECT_CONNECTION_LOST 10
#define SSH2_DISCONNECT_BY_APPLICATION 11
/* misc */
#define SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED 1
#define SSH2_OPEN_CONNECT_FAILED 2
#define SSH2_OPEN_UNKNOWN_CHANNEL_TYPE 3
#define SSH2_OPEN_RESOURCE_SHORTAGE 4
#define SSH2_EXTENDED_DATA_STDERR 1

10
sshd.8
Просмотреть файл

@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\"
.\" $Id: sshd.8,v 1.15 2000/03/26 03:04:55 damien Exp $
.\" $Id: sshd.8,v 1.16 2000/04/01 01:09:27 damien Exp $
.\"
.Dd September 25, 1999
.Dt SSHD 8
@ -69,7 +69,7 @@ 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.
being used by default.
The client selects the encryption algorithm
to use from those offered by the server.
.Pp
@ -877,11 +877,11 @@ The libraries described in
.Xr ssl 8
are required for proper operation.
.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

1855
sshd.c

Разница между файлами не показана из-за своего большого размера Загрузить разницу