mirror of
https://github.com/PowerShell/openssh-portable.git
synced 2025-07-29 16:54:51 +02:00
- 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:
parent
450a7a1ff4
commit
b38eff8e4f
32
ChangeLog
32
ChangeLog
@ -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
|
20000326
|
||||||
- Better tests for OpenSSL w/ RSAref
|
- Better tests for OpenSSL w/ RSAref
|
||||||
- Added replacement setenv() function from OpenBSD libc. Suggested by
|
- 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)
|
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
|
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
|
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
|
CATMAN = scp.0 ssh-add.0 ssh-agent.0 ssh-keygen.0 ssh.0 sshd.0
|
||||||
|
606
auth.c
Normal file
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
6
auth.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#ifndef AUTH_H
|
||||||
|
#define AUTH_H
|
||||||
|
|
||||||
|
void do_authentication(void);
|
||||||
|
|
||||||
|
#endif
|
53
bufaux.c
53
bufaux.c
@ -12,10 +12,12 @@
|
|||||||
* Auxiliary functions for storing and retrieving various data types to/from
|
* Auxiliary functions for storing and retrieving various data types to/from
|
||||||
* Buffers.
|
* Buffers.
|
||||||
*
|
*
|
||||||
|
* SSH2 packet format added by Markus Friedl
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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"
|
#include "ssh.h"
|
||||||
|
|
||||||
@ -82,6 +84,50 @@ buffer_get_bignum(Buffer *buffer, BIGNUM *value)
|
|||||||
return 2 + bytes;
|
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).
|
* 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_put_int(buffer, len);
|
||||||
buffer_append(buffer, buf, 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).
|
* Returns a character from the buffer (0 - 255).
|
||||||
|
5
bufaux.h
5
bufaux.h
@ -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
|
#ifndef BUFAUX_H
|
||||||
#define BUFAUX_H
|
#define BUFAUX_H
|
||||||
@ -23,9 +23,11 @@
|
|||||||
* by (bits+7)/8 bytes of binary data, msb first.
|
* by (bits+7)/8 bytes of binary data, msb first.
|
||||||
*/
|
*/
|
||||||
void buffer_put_bignum(Buffer * buffer, BIGNUM * value);
|
void buffer_put_bignum(Buffer * buffer, BIGNUM * value);
|
||||||
|
void buffer_put_bignum2(Buffer * buffer, BIGNUM * value);
|
||||||
|
|
||||||
/* Retrieves an BIGNUM from the buffer. */
|
/* Retrieves an BIGNUM from the buffer. */
|
||||||
int buffer_get_bignum(Buffer * buffer, BIGNUM * value);
|
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). */
|
/* Returns an integer from the buffer (4 bytes, msb first). */
|
||||||
unsigned int buffer_get_int(Buffer * buffer);
|
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. */
|
/* Stores and arbitrary binary string in the buffer. */
|
||||||
void buffer_put_string(Buffer * buffer, const void *buf, unsigned int len);
|
void buffer_put_string(Buffer * buffer, const void *buf, unsigned int len);
|
||||||
|
void buffer_put_cstring(Buffer *buffer, const char *s);
|
||||||
|
|
||||||
#endif /* BUFAUX_H */
|
#endif /* BUFAUX_H */
|
||||||
|
1244
channels.c
1244
channels.c
File diff suppressed because it is too large
Load Diff
194
channels.h
194
channels.h
@ -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
|
#ifndef CHANNELS_H
|
||||||
#define CHANNELS_H
|
#define CHANNELS_H
|
||||||
@ -10,17 +10,18 @@
|
|||||||
#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
|
#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
|
||||||
#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
|
#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
|
||||||
#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
|
#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
|
||||||
/* SSH_CHANNEL_AUTH_FD 6 authentication fd */
|
#define SSH_CHANNEL_AUTH_SOCKET 6 /* authentication socket */
|
||||||
#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
|
#define SSH_CHANNEL_X11_OPEN 7 /* reading first X11 packet */
|
||||||
/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */
|
#define SSH_CHANNEL_INPUT_DRAINING 8 /* sending remaining data to conn */
|
||||||
#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
|
#define SSH_CHANNEL_OUTPUT_DRAINING 9 /* sending remaining data to app */
|
||||||
#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */
|
#define SSH_CHANNEL_LARVAL 10 /* larval session */
|
||||||
#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */
|
#define SSH_CHANNEL_MAX_TYPE 11
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data structure for channel data. This is iniailized in channel_allocate
|
* Data structure for channel data. This is iniailized in channel_allocate
|
||||||
* and cleared in channel_free.
|
* and cleared in channel_free.
|
||||||
*/
|
*/
|
||||||
|
typedef void channel_callback_fn(int id, void *arg);
|
||||||
|
|
||||||
typedef struct Channel {
|
typedef struct Channel {
|
||||||
int type; /* channel type/state */
|
int type; /* channel type/state */
|
||||||
@ -29,15 +30,192 @@ typedef struct Channel {
|
|||||||
/* peer can be reached over encrypted connection, via packet-sent */
|
/* peer can be reached over encrypted connection, via packet-sent */
|
||||||
int istate; /* input from channel (state of receive half) */
|
int istate; /* input from channel (state of receive half) */
|
||||||
int ostate; /* output to channel (state of transmit 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
|
Buffer input; /* data read from socket, to be sent over
|
||||||
* encrypted connection */
|
* encrypted connection */
|
||||||
Buffer output; /* data received over encrypted connection for
|
Buffer output; /* data received over encrypted connection for
|
||||||
* send on socket */
|
* send on socket */
|
||||||
|
Buffer extended;
|
||||||
char path[200]; /* path for unix domain sockets, or host name
|
char path[200]; /* path for unix domain sockets, or host name
|
||||||
* for forwards */
|
* for forwards */
|
||||||
int listening_port; /* port being listened for forwards */
|
int listening_port; /* port being listened for forwards */
|
||||||
int host_port; /* remote port to connect for forwards */
|
int host_port; /* remote port to connect for forwards */
|
||||||
char *remote_name; /* remote hostname */
|
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;
|
} 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
|
#endif
|
||||||
|
123
cipher.c
123
cipher.c
@ -12,7 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "ssh.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
@ -122,7 +122,12 @@ static char *cipher_names[] =
|
|||||||
"3des",
|
"3des",
|
||||||
"tss",
|
"tss",
|
||||||
"rc4",
|
"rc4",
|
||||||
"blowfish"
|
"blowfish",
|
||||||
|
"reserved",
|
||||||
|
"blowfish-cbc",
|
||||||
|
"3des-cbc",
|
||||||
|
"arcfour",
|
||||||
|
"cast128-cbc"
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -137,6 +142,10 @@ cipher_mask()
|
|||||||
unsigned int mask = 0;
|
unsigned int mask = 0;
|
||||||
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
|
mask |= 1 << SSH_CIPHER_3DES; /* Mandatory */
|
||||||
mask |= 1 << SSH_CIPHER_BLOWFISH;
|
mask |= 1 << SSH_CIPHER_BLOWFISH;
|
||||||
|
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;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,16 +242,84 @@ cipher_set_key(CipherContext *context, int cipher,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SSH_CIPHER_BLOWFISH:
|
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);
|
BF_set_key(&context->u.bf.key, keylen, padded);
|
||||||
memset(context->u.bf.iv, 0, 8);
|
memset(context->u.bf.iv, 0, 8);
|
||||||
break;
|
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:
|
default:
|
||||||
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
|
fatal("cipher_set_key: unknown cipher: %s", cipher_name(cipher));
|
||||||
}
|
}
|
||||||
memset(padded, 0, sizeof(padded));
|
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. */
|
/* Encrypts data using the cipher. */
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -272,6 +349,27 @@ cipher_encrypt(CipherContext *context, unsigned char *dest,
|
|||||||
swap_bytes(dest, dest, len);
|
swap_bytes(dest, dest, len);
|
||||||
break;
|
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:
|
default:
|
||||||
fatal("cipher_encrypt: unknown cipher: %s", cipher_name(context->type));
|
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);
|
swap_bytes(dest, dest, len);
|
||||||
break;
|
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:
|
default:
|
||||||
fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
|
fatal("cipher_decrypt: unknown cipher: %s", cipher_name(context->type));
|
||||||
}
|
}
|
||||||
|
22
cipher.h
22
cipher.h
@ -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
|
#ifndef CIPHER_H
|
||||||
#define CIPHER_H
|
#define CIPHER_H
|
||||||
@ -21,10 +21,14 @@
|
|||||||
#ifdef HAVE_OPENSSL
|
#ifdef HAVE_OPENSSL
|
||||||
#include <openssl/des.h>
|
#include <openssl/des.h>
|
||||||
#include <openssl/blowfish.h>
|
#include <openssl/blowfish.h>
|
||||||
|
#include <openssl/rc4.h>
|
||||||
|
#include <openssl/cast.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
#include <ssl/des.h>
|
#include <ssl/des.h>
|
||||||
#include <ssl/blowfish.h>
|
#include <ssl/blowfish.h>
|
||||||
|
#include <ssl/rc4.h>
|
||||||
|
#include <ssl/cast.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Cipher types. New types can be added, but old types should not be removed
|
/* 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_TSS 4 /* TRI's Simple Stream encryption CBC */
|
||||||
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
|
#define SSH_CIPHER_BROKEN_RC4 5 /* Alleged RC4 */
|
||||||
#define SSH_CIPHER_BLOWFISH 6
|
#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 {
|
typedef struct {
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
@ -52,6 +63,11 @@ typedef struct {
|
|||||||
struct bf_key_st key;
|
struct bf_key_st key;
|
||||||
unsigned char iv[8];
|
unsigned char iv[8];
|
||||||
} bf;
|
} bf;
|
||||||
|
struct {
|
||||||
|
CAST_KEY key;
|
||||||
|
unsigned char iv[8];
|
||||||
|
} cast;
|
||||||
|
RC4_KEY rc4;
|
||||||
} u;
|
} u;
|
||||||
} CipherContext;
|
} CipherContext;
|
||||||
/*
|
/*
|
||||||
@ -77,6 +93,10 @@ int cipher_number(const char *name);
|
|||||||
void
|
void
|
||||||
cipher_set_key(CipherContext * context, int cipher,
|
cipher_set_key(CipherContext * context, int cipher,
|
||||||
const unsigned char *key, int keylen, int for_encryption);
|
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,
|
* Sets key for the cipher by computing the MD5 checksum of the passphrase,
|
||||||
|
205
clientloop.c
205
clientloop.c
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "ssh.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 "authfd.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
#include "channels.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
|
||||||
|
|
||||||
/* Flag indicating that stdin should be redirected from /dev/null. */
|
/* Flag indicating that stdin should be redirected from /dev/null. */
|
||||||
extern int stdin_null_flag;
|
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
|
* 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
|
* Implements the interactive session with the server. This is called after
|
||||||
* the user has been authenticated, and a command has been started on the
|
* 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.
|
* character for terminating or suspending the session.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
void client_init_dispatch(void);
|
||||||
|
|
||||||
int
|
int
|
||||||
client_loop(int have_pty, int escape_char_arg)
|
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(&stdout_buffer);
|
||||||
buffer_init(&stderr_buffer);
|
buffer_init(&stderr_buffer);
|
||||||
|
|
||||||
|
client_init_dispatch();
|
||||||
|
|
||||||
/* Set signal handlers to restore non-blocking mode. */
|
/* Set signal handlers to restore non-blocking mode. */
|
||||||
signal(SIGINT, signal_handler);
|
signal(SIGINT, signal_handler);
|
||||||
signal(SIGQUIT, 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);
|
debug("Exit status %d", exit_status);
|
||||||
return 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();
|
||||||
|
}
|
||||||
|
40
compress.c
40
compress.c
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "ssh.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
@ -90,23 +90,13 @@ buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
|
|||||||
case Z_OK:
|
case Z_OK:
|
||||||
/* Append compressed data to output_buffer. */
|
/* Append compressed data to output_buffer. */
|
||||||
buffer_append(output_buffer, buf,
|
buffer_append(output_buffer, buf,
|
||||||
sizeof(buf) - outgoing_stream.avail_out);
|
sizeof(buf) - outgoing_stream.avail_out);
|
||||||
break;
|
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:
|
default:
|
||||||
fatal("buffer_compress: deflate returned %d", status);
|
fatal("buffer_compress: deflate returned %d", status);
|
||||||
/* NOTREACHED */
|
/* 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.next_in = (unsigned char *) buffer_ptr(input_buffer);
|
||||||
incoming_stream.avail_in = buffer_len(input_buffer);
|
incoming_stream.avail_in = buffer_len(input_buffer);
|
||||||
|
|
||||||
incoming_stream.next_out = (unsigned char *) buf;
|
|
||||||
incoming_stream.avail_out = sizeof(buf);
|
|
||||||
|
|
||||||
for (;;) {
|
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);
|
status = inflate(&incoming_stream, Z_PARTIAL_FLUSH);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case Z_OK:
|
case Z_OK:
|
||||||
buffer_append(output_buffer, buf,
|
buffer_append(output_buffer, buf,
|
||||||
sizeof(buf) - incoming_stream.avail_out);
|
sizeof(buf) - incoming_stream.avail_out);
|
||||||
incoming_stream.next_out = (unsigned char *) buf;
|
|
||||||
incoming_stream.avail_out = sizeof(buf);
|
|
||||||
break;
|
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:
|
case Z_BUF_ERROR:
|
||||||
/*
|
/*
|
||||||
* Comments in zlib.h say that we should keep calling
|
* 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.
|
* be the error that we get.
|
||||||
*/
|
*/
|
||||||
return;
|
return;
|
||||||
case Z_MEM_ERROR:
|
|
||||||
fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");
|
|
||||||
/* NOTREACHED */
|
|
||||||
default:
|
default:
|
||||||
fatal("buffer_uncompress: inflate returned %d", status);
|
fatal("buffer_uncompress: inflate returned %d", status);
|
||||||
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
78
dispatch.c
Normal file
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
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);
|
12
log-server.c
12
log-server.c
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 <syslog.h>
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
@ -137,9 +137,11 @@ do_log(LogLevel level, const char *fmt, va_list args)
|
|||||||
} else {
|
} else {
|
||||||
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
|
vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
|
||||||
}
|
}
|
||||||
if (log_on_stderr)
|
if (log_on_stderr) {
|
||||||
fprintf(stderr, "%s\n", msgbuf);
|
fprintf(stderr, "%s\n", msgbuf);
|
||||||
openlog(__progname, LOG_PID, log_facility);
|
} else {
|
||||||
syslog(pri, "%.500s", msgbuf);
|
openlog(__progname, LOG_PID, log_facility);
|
||||||
closelog();
|
syslog(pri, "%.500s", msgbuf);
|
||||||
|
closelog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8
mpaux.c
8
mpaux.c
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "getput.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
@ -31,9 +31,9 @@ RCSID("$Id: mpaux.c,v 1.8 1999/12/13 23:47:16 damien Exp $");
|
|||||||
|
|
||||||
void
|
void
|
||||||
compute_session_id(unsigned char session_id[16],
|
compute_session_id(unsigned char session_id[16],
|
||||||
unsigned char cookie[8],
|
unsigned char cookie[8],
|
||||||
BIGNUM* host_key_n,
|
BIGNUM* host_key_n,
|
||||||
BIGNUM* session_key_n)
|
BIGNUM* session_key_n)
|
||||||
{
|
{
|
||||||
unsigned int host_key_bytes = BN_num_bytes(host_key_n);
|
unsigned int host_key_bytes = BN_num_bytes(host_key_n);
|
||||||
unsigned int session_key_bytes = BN_num_bytes(session_key_n);
|
unsigned int session_key_bytes = BN_num_bytes(session_key_n);
|
||||||
|
9
nchan.c
9
nchan.c
@ -28,7 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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"
|
#include "ssh.h"
|
||||||
|
|
||||||
@ -41,7 +41,6 @@ static void chan_send_ieof(Channel *c);
|
|||||||
static void chan_send_oclose(Channel *c);
|
static void chan_send_oclose(Channel *c);
|
||||||
static void chan_shutdown_write(Channel *c);
|
static void chan_shutdown_write(Channel *c);
|
||||||
static void chan_shutdown_read(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
|
* 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);
|
error("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chan_delete_if_full_closed(c);
|
|
||||||
}
|
}
|
||||||
void
|
void
|
||||||
chan_read_failed(Channel *c)
|
chan_read_failed(Channel *c)
|
||||||
@ -121,7 +119,6 @@ chan_rcvd_ieof(Channel *c)
|
|||||||
case CHAN_OUTPUT_WAIT_IEOF:
|
case CHAN_OUTPUT_WAIT_IEOF:
|
||||||
debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
|
debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
|
||||||
c->ostate = CHAN_OUTPUT_CLOSED;
|
c->ostate = CHAN_OUTPUT_CLOSED;
|
||||||
chan_delete_if_full_closed(c);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
|
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);
|
debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
|
||||||
chan_send_oclose(c);
|
chan_send_oclose(c);
|
||||||
c->ostate = CHAN_OUTPUT_CLOSED;
|
c->ostate = CHAN_OUTPUT_CLOSED;
|
||||||
chan_delete_if_full_closed(c);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
|
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);
|
debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
|
||||||
chan_send_oclose(c);
|
chan_send_oclose(c);
|
||||||
c->ostate = CHAN_OUTPUT_CLOSED;
|
c->ostate = CHAN_OUTPUT_CLOSED;
|
||||||
chan_delete_if_full_closed(c);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
|
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",
|
error("chan_shutdown_read failed for #%d/fd%d [i%d o%d]: %.100s",
|
||||||
c->self, c->sock, c->istate, c->ostate, strerror(errno));
|
c->self, c->sock, c->istate, c->ostate, strerror(errno));
|
||||||
}
|
}
|
||||||
static void
|
void
|
||||||
chan_delete_if_full_closed(Channel *c)
|
chan_delete_if_full_closed(Channel *c)
|
||||||
{
|
{
|
||||||
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
|
if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
|
||||||
|
4
nchan.h
4
nchan.h
@ -27,7 +27,7 @@
|
|||||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* 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
|
#ifndef NCHAN_H
|
||||||
#define NCHAN_H
|
#define NCHAN_H
|
||||||
@ -83,4 +83,6 @@ void chan_write_failed(Channel * c);
|
|||||||
void chan_obuf_empty(Channel * c);
|
void chan_obuf_empty(Channel * c);
|
||||||
|
|
||||||
void chan_init_iostates(Channel * c);
|
void chan_init_iostates(Channel * c);
|
||||||
|
|
||||||
|
void chan_delete_if_full_closed(Channel *c);
|
||||||
#endif
|
#endif
|
||||||
|
3
packet.c
3
packet.c
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "buffer.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 "compress.h"
|
||||||
#include "deattack.h"
|
#include "deattack.h"
|
||||||
|
#include "channels.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This variable contains the file descriptors used for communicating with
|
* This variable contains the file descriptors used for communicating with
|
||||||
|
4
pty.h
4
pty.h
@ -13,7 +13,7 @@
|
|||||||
* tty.
|
* 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
|
#ifndef PTY_H
|
||||||
#define 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);
|
||||||
|
|
||||||
void pty_setowner(struct passwd *pw, const char *ttyname);
|
|
||||||
|
|
||||||
#endif /* PTY_H */
|
#endif /* PTY_H */
|
||||||
|
@ -14,11 +14,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "ssh.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
|
#include "match.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* Format of the configuration file:
|
/* Format of the configuration file:
|
||||||
|
195
serverloop.c
195
serverloop.c
@ -13,6 +13,10 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "servconf.h"
|
#include "servconf.h"
|
||||||
#include "pty.h"
|
#include "pty.h"
|
||||||
|
#include "channels.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
#include "dispatch.h"
|
||||||
|
|
||||||
static Buffer stdin_buffer; /* Buffer for stdin data. */
|
static Buffer stdin_buffer; /* Buffer for stdin data. */
|
||||||
static Buffer stdout_buffer; /* Buffer for stdout data. */
|
static Buffer stdout_buffer; /* Buffer for stdout data. */
|
||||||
@ -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_has_selected; /* Child has had chance to drain. */
|
||||||
static volatile int child_wait_status; /* Status from wait(). */
|
static volatile int child_wait_status; /* Status from wait(). */
|
||||||
|
|
||||||
|
void server_init_dispatch(void);
|
||||||
|
|
||||||
void
|
void
|
||||||
sigchld_handler(int sig)
|
sigchld_handler(int sig)
|
||||||
{
|
{
|
||||||
@ -67,104 +73,6 @@ sigchld_handler(int sig)
|
|||||||
errno = save_errno;
|
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
|
* Make packets from buffered stderr data, and buffer it for sending
|
||||||
* to the client.
|
* to the client.
|
||||||
@ -378,7 +286,7 @@ process_output(fd_set * writeset)
|
|||||||
#ifdef USE_PIPES
|
#ifdef USE_PIPES
|
||||||
close(fdin);
|
close(fdin);
|
||||||
#else
|
#else
|
||||||
if (fdout == -1)
|
if (fdin != fdout)
|
||||||
close(fdin);
|
close(fdin);
|
||||||
else
|
else
|
||||||
shutdown(fdin, SHUT_WR); /* We will no longer send. */
|
shutdown(fdin, SHUT_WR); /* We will no longer send. */
|
||||||
@ -425,6 +333,12 @@ drain_output()
|
|||||||
packet_write_wait();
|
packet_write_wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
process_buffered_input_packets()
|
||||||
|
{
|
||||||
|
dispatch_run(DISPATCH_NONBLOCK, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Performs the interactive session. This handles data transmission between
|
* Performs the interactive session. This handles data transmission between
|
||||||
* the client and the program. Note that the notion of stdin, stdout, and
|
* 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)
|
if (fderr == -1)
|
||||||
fderr_eof = 1;
|
fderr_eof = 1;
|
||||||
|
|
||||||
|
server_init_dispatch();
|
||||||
|
|
||||||
/* Main loop of the server for the interactive session mode. */
|
/* Main loop of the server for the interactive session mode. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
fd_set readset, writeset;
|
fd_set readset, writeset;
|
||||||
@ -505,7 +421,7 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
|
|||||||
#ifdef USE_PIPES
|
#ifdef USE_PIPES
|
||||||
close(fdin);
|
close(fdin);
|
||||||
#else
|
#else
|
||||||
if (fdout == -1)
|
if (fdin != fdout)
|
||||||
close(fdin);
|
close(fdin);
|
||||||
else
|
else
|
||||||
shutdown(fdin, SHUT_WR); /* We will no longer send. */
|
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(&stdout_buffer) == 0) &&
|
||||||
(buffer_len(&stderr_buffer) == 0)) {
|
(buffer_len(&stderr_buffer) == 0)) {
|
||||||
if (!channel_still_open())
|
if (!channel_still_open())
|
||||||
goto quit;
|
break;
|
||||||
if (!waiting_termination) {
|
if (!waiting_termination) {
|
||||||
const char *s = "Waiting for forwarded connections to terminate...\r\n";
|
const char *s = "Waiting for forwarded connections to terminate...\r\n";
|
||||||
char *cp;
|
char *cp;
|
||||||
@ -576,7 +492,6 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
|
|||||||
process_output(&writeset);
|
process_output(&writeset);
|
||||||
}
|
}
|
||||||
|
|
||||||
quit:
|
|
||||||
/* Cleanup and termination code. */
|
/* Cleanup and termination code. */
|
||||||
|
|
||||||
/* Wait until all output has been sent to the client. */
|
/* Wait until all output has been sent to the client. */
|
||||||
@ -662,3 +577,79 @@ quit:
|
|||||||
packet_disconnect("wait returned status %04x.", wait_status);
|
packet_disconnect("wait returned status %04x.", wait_status);
|
||||||
/* NOTREACHED */
|
/* 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();
|
||||||
|
}
|
||||||
|
7
session.h
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
3
ssh.c
@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "includes.h"
|
#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 "xmalloc.h"
|
||||||
#include "ssh.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 "authfd.h"
|
||||||
#include "readconf.h"
|
#include "readconf.h"
|
||||||
#include "uidswap.h"
|
#include "uidswap.h"
|
||||||
|
#include "channels.h"
|
||||||
|
|
||||||
#ifdef HAVE___PROGNAME
|
#ifdef HAVE___PROGNAME
|
||||||
extern char *__progname;
|
extern char *__progname;
|
||||||
|
171
ssh.h
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
|
#ifndef SSH_H
|
||||||
#define 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(). */
|
/* Removes a cleanup function to be called at fatal(). */
|
||||||
void fatal_remove_cleanup(void (*proc) (void *context), void *context);
|
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.
|
* Expands tildes in the file name. Returns data allocated by xmalloc.
|
||||||
* Warning: this calls getpw*.
|
* Warning: this calls getpw*.
|
||||||
|
106
ssh2.h
Normal file
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
10
sshd.8
@ -9,7 +9,7 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" Created: Sat Apr 22 21:55:14 1995 ylo
|
.\" 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
|
.Dd September 25, 1999
|
||||||
.Dt SSHD 8
|
.Dt SSHD 8
|
||||||
@ -69,7 +69,7 @@ random number as a session key which is used to encrypt all further
|
|||||||
communications in the session.
|
communications in the session.
|
||||||
The rest of the session is encrypted
|
The rest of the session is encrypted
|
||||||
using a conventional cipher, currently Blowfish and 3DES, with 3DES
|
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
|
The client selects the encryption algorithm
|
||||||
to use from those offered by the server.
|
to use from those offered by the server.
|
||||||
.Pp
|
.Pp
|
||||||
@ -877,11 +877,11 @@ The libraries described in
|
|||||||
.Xr ssl 8
|
.Xr ssl 8
|
||||||
are required for proper operation.
|
are required for proper operation.
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr rlogin 1 ,
|
|
||||||
.Xr rsh 1 ,
|
|
||||||
.Xr scp 1 ,
|
.Xr scp 1 ,
|
||||||
.Xr ssh 1 ,
|
.Xr ssh 1 ,
|
||||||
.Xr ssh-add 1 ,
|
.Xr ssh-add 1 ,
|
||||||
.Xr ssh-agent 1 ,
|
.Xr ssh-agent 1 ,
|
||||||
.Xr ssh-keygen 1 ,
|
.Xr ssh-keygen 1 ,
|
||||||
.Xr ssl 8
|
.Xr ssl 8 ,
|
||||||
|
.Xr rlogin 1 ,
|
||||||
|
.Xr rsh 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user