- More reformatting merged from OpenBSD CVS

- Merged OpenBSD CVS changes:
   - [channels.c]
     report from mrwizard@psu.edu via djm@ibs.com.au
   - [channels.c]
     set SO_REUSEADDR and SO_LINGER for forwarded ports.
     chip@valinux.com via damien@ibs.com.au
   - [nchan.c]
     it's not an error() if shutdown_write failes in nchan.
   - [readconf.c]
     remove dead #ifdef-0-code
   - [readconf.c servconf.c]
     strcasecmp instead of tolower
   - [scp.c]
     progress meter overflow fix from damien@ibs.com.au
   - [ssh-add.1 ssh-add.c]
     SSH_ASKPASS support
   - [ssh.1 ssh.c]
     postpone fork_after_authentication until command execution,
     request/patch from jahakala@cc.jyu.fi via damien@ibs.com.au
     plus: use daemon() for backgrounding
This commit is contained in:
Damien Miller 1999-11-25 11:54:57 +11:00
Родитель 9072e18896
Коммит 5428f646ad
61 изменённых файлов: 2681 добавлений и 1798 удалений

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

@ -11,7 +11,7 @@
#ifndef HAVE_PAM
RCSID("$Id: auth-passwd.c,v 1.6 1999/11/24 13:26:21 damien Exp $");
RCSID("$Id: auth-passwd.c,v 1.7 1999/11/25 00:54:57 damien Exp $");
#include "packet.h"
#include "ssh.h"
@ -39,14 +39,10 @@ auth_password(struct passwd * pw, const char *password)
struct spwd *spw;
#endif
if (pw->pw_uid == 0 && options.permit_root_login == 2) {
/* Server does not permit root login with password */
if (pw->pw_uid == 0 && options.permit_root_login == 2)
return 0;
}
if (*password == '\0' && options.permit_empty_passwd == 0) {
/* Server does not permit empty password login */
if (*password == '\0' && options.permit_empty_passwd == 0)
return 0;
}
/* deny if no user. */
if (pw == NULL)
return 0;
@ -74,8 +70,10 @@ auth_password(struct passwd * pw, const char *password)
#endif
#if defined(KRB4)
/* Support for Kerberos v4 authentication - Dug Song
<dugsong@UMICH.EDU> */
/*
* Support for Kerberos v4 authentication
* - Dug Song <dugsong@UMICH.EDU>
*/
if (options.kerberos_authentication) {
AUTH_DAT adata;
KTEXT_ST tkt;
@ -86,8 +84,10 @@ auth_password(struct passwd * pw, const char *password)
char realm[REALM_SZ];
int r;
/* Try Kerberos password authentication only for non-root
users and only if Kerberos is installed. */
/*
* Try Kerberos password authentication only for non-root
* users and only if Kerberos is installed.
*/
if (pw->pw_uid != 0 && krb_get_lrealm(realm, 1) == KSUCCESS) {
/* Set up our ticket file. */
@ -144,14 +144,17 @@ auth_password(struct passwd * pw, const char *password)
goto kerberos_auth_failure;
}
} else if (r == KDC_PR_UNKNOWN) {
/* Allow login if no rcmd service exists,
but log the error. */
/*
* Allow login if no rcmd service exists, but
* log the error.
*/
log("Kerberos V4 TGT for %s unverifiable: %s; %s.%s "
"not registered, or srvtab is wrong?", pw->pw_name,
krb_err_txt[r], KRB4_SERVICE_NAME, phost);
} else {
/* TGT is bad, forget it. Possibly
spoofed! */
/*
* TGT is bad, forget it. Possibly spoofed!
*/
packet_send_debug("WARNING: Kerberos V4 TGT "
"possibly spoofed for %s: %s",
pw->pw_name, krb_err_txt[r]);
@ -175,11 +178,8 @@ auth_password(struct passwd * pw, const char *password)
#endif /* KRB4 */
/* Check for users with no password. */
if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0) {
packet_send_debug("Login permitted without a password "
"because the account has no password.");
if (strcmp(password, "") == 0 && strcmp(pw->pw_passwd, "") == 0)
return 1;
}
#ifdef HAVE_SHADOW_H
spw = getspnam(pw->pw_name);

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

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: auth-rh-rsa.c,v 1.6 1999/11/24 13:26:21 damien Exp $");
RCSID("$Id: auth-rh-rsa.c,v 1.7 1999/11/25 00:54:57 damien Exp $");
#include "packet.h"
#include "ssh.h"
@ -23,8 +23,10 @@ RCSID("$Id: auth-rh-rsa.c,v 1.6 1999/11/24 13:26:21 damien Exp $");
#include "uidswap.h"
#include "servconf.h"
/* Tries to authenticate the user using the .rhosts file and the host using
its host key. Returns true if authentication succeeds. */
/*
* Tries to authenticate the user using the .rhosts file and the host using
* its host key. Returns true if authentication succeeds.
*/
int
auth_rhosts_rsa(struct passwd *pw, const char *client_user,
@ -57,8 +59,10 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user,
if (host_status != HOST_OK && !options.ignore_user_known_hosts) {
struct stat st;
char *user_hostfile = tilde_expand_filename(SSH_USER_HOSTFILE, pw->pw_uid);
/* Check file permissions of SSH_USER_HOSTFILE, auth_rsa()
did already check pw->pw_dir, but there is a race XXX */
/*
* Check file permissions of SSH_USER_HOSTFILE, auth_rsa()
* did already check pw->pw_dir, but there is a race XXX
*/
if (options.strict_modes &&
(stat(user_hostfile, &st) == 0) &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
@ -91,8 +95,10 @@ auth_rhosts_rsa(struct passwd *pw, const char *client_user,
canonical_hostname);
return 0;
}
/* We have authenticated the user using .rhosts or /etc/hosts.equiv, and the host using RSA.
We accept the authentication. */
/*
* We have authenticated the user using .rhosts or /etc/hosts.equiv,
* and the host using RSA. We accept the authentication.
*/
verbose("Rhosts with RSA host authentication accepted for %.100s, %.100s on %.700s.",
pw->pw_name, client_user, canonical_hostname);

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

@ -16,7 +16,7 @@
*/
#include "includes.h"
RCSID("$Id: auth-rhosts.c,v 1.5 1999/11/24 13:26:21 damien Exp $");
RCSID("$Id: auth-rhosts.c,v 1.6 1999/11/25 00:54:57 damien Exp $");
#include "packet.h"
#include "ssh.h"
@ -24,9 +24,11 @@ RCSID("$Id: auth-rhosts.c,v 1.5 1999/11/24 13:26:21 damien Exp $");
#include "uidswap.h"
#include "servconf.h"
/* This function processes an rhosts-style file (.rhosts, .shosts, or
/etc/hosts.equiv). This returns true if authentication can be granted
based on the file, and returns zero otherwise. */
/*
* This function processes an rhosts-style file (.rhosts, .shosts, or
* /etc/hosts.equiv). This returns true if authentication can be granted
* based on the file, and returns zero otherwise.
*/
int
check_rhosts_file(const char *filename, const char *hostname,
@ -41,7 +43,6 @@ check_rhosts_file(const char *filename, const char *hostname,
if (!f)
return 0;
/* Go through the file, checking every entry. */
while (fgets(buf, sizeof(buf), f)) {
/* All three must be at least as big as buf to avoid overflows. */
char hostbuf[1024], userbuf[1024], dummy[1024], *host, *user, *cp;
@ -52,13 +53,17 @@ check_rhosts_file(const char *filename, const char *hostname,
if (*cp == '#' || *cp == '\n' || !*cp)
continue;
/* NO_PLUS is supported at least on OSF/1. We skip it (we
don't ever support the plus syntax). */
/*
* NO_PLUS is supported at least on OSF/1. We skip it (we
* don't ever support the plus syntax).
*/
if (strncmp(cp, "NO_PLUS", 7) == 0)
continue;
/* This should be safe because each buffer is as big as
the whole string, and thus cannot be overwritten. */
/*
* This should be safe because each buffer is as big as the
* whole string, and thus cannot be overwritten.
*/
switch (sscanf(buf, "%s %s %s", hostbuf, userbuf, dummy)) {
case 0:
packet_send_debug("Found empty line in %.100s.", filename);
@ -135,10 +140,11 @@ check_rhosts_file(const char *filename, const char *hostname,
return 0;
}
/* Tries to authenticate the user using the .shosts or .rhosts file.
Returns true if authentication succeeds. If ignore_rhosts is
true, only /etc/hosts.equiv will be considered (.rhosts and .shosts
are ignored). */
/*
* Tries to authenticate the user using the .shosts or .rhosts file. Returns
* true if authentication succeeds. If ignore_rhosts is true, only
* /etc/hosts.equiv will be considered (.rhosts and .shosts are ignored).
*/
int
auth_rhosts(struct passwd *pw, const char *client_user)
@ -150,11 +156,13 @@ auth_rhosts(struct passwd *pw, const char *client_user)
static const char *rhosts_files[] = {".shosts", ".rhosts", NULL};
unsigned int rhosts_file_index;
/* Quick check: if the user has no .shosts or .rhosts files,
return failure immediately without doing costly lookups from
name servers. */
/* Switch to the user's uid. */
temporarily_use_uid(pw->pw_uid);
/*
* Quick check: if the user has no .shosts or .rhosts files, return
* failure immediately without doing costly lookups from name
* servers.
*/
for (rhosts_file_index = 0; rhosts_files[rhosts_file_index];
rhosts_file_index++) {
/* Check users .rhosts or .shosts. */
@ -172,7 +180,6 @@ auth_rhosts(struct passwd *pw, const char *client_user)
stat(SSH_HOSTS_EQUIV, &st) < 0)
return 0;
/* Get the name, address, and port of the remote host. */
hostname = get_canonical_hostname();
ipaddr = get_remote_ipaddr();
@ -191,8 +198,10 @@ auth_rhosts(struct passwd *pw, const char *client_user)
return 1;
}
}
/* Check that the home directory is owned by root or the user, and
is not group or world writable. */
/*
* Check that the home directory is owned by root or the user, and is
* not group or world writable.
*/
if (stat(pw->pw_dir, &st) < 0) {
log("Rhosts authentication refused for %.100s: no home directory %.200s",
pw->pw_name, pw->pw_dir);
@ -221,10 +230,12 @@ auth_rhosts(struct passwd *pw, const char *client_user)
if (stat(buf, &st) < 0)
continue;
/* Make sure that the file is either owned by the user or
by root, and make sure it is not writable by anyone but
the owner. This is to help avoid novices accidentally
allowing access to their account by anyone. */
/*
* Make sure that the file is either owned by the user or by
* root, and make sure it is not writable by anyone but the
* owner. This is to help avoid novices accidentally
* allowing access to their account by anyone.
*/
if (options.strict_modes &&
((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
(st.st_mode & 022) != 0)) {

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

@ -16,7 +16,7 @@
*/
#include "includes.h"
RCSID("$Id: auth-rsa.c,v 1.9 1999/11/24 13:26:21 damien Exp $");
RCSID("$Id: auth-rsa.c,v 1.10 1999/11/25 00:54:57 damien Exp $");
#include "rsa.h"
#include "packet.h"
@ -43,22 +43,27 @@ extern int no_pty_flag;
extern char *forced_command;
extern struct envstring *custom_environment;
/* Session identifier that is used to bind key exchange and authentication
responses to a particular session. */
/*
* Session identifier that is used to bind key exchange and authentication
* responses to a particular session.
*/
extern unsigned char session_id[16];
/* The .ssh/authorized_keys file contains public keys, one per line, in the
following format:
options bits e n comment
where bits, e and n are decimal numbers,
and comment is any string of characters up to newline. The maximum
length of a line is 8000 characters. See the documentation for a
description of the options.
*/
/*
* The .ssh/authorized_keys file contains public keys, one per line, in the
* following format:
* options bits e n comment
* where bits, e and n are decimal numbers,
* and comment is any string of characters up to newline. The maximum
* length of a line is 8000 characters. See the documentation for a
* description of the options.
*/
/* Performs the RSA authentication challenge-response dialog with the client,
and returns true (non-zero) if the client gave the correct answer to
our challenge; returns zero if the client gives a wrong answer. */
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to
* our challenge; returns zero if the client gives a wrong answer.
*/
int
auth_rsa_challenge_dialog(BIGNUM *e, BIGNUM *n)
@ -128,9 +133,11 @@ auth_rsa_challenge_dialog(BIGNUM *e, BIGNUM *n)
return 1;
}
/* Performs the RSA authentication dialog with the client. This returns
0 if the client could not be authenticated, and 1 if authentication was
successful. This may exit if there is a serious protocol violation. */
/*
* Performs the RSA authentication dialog with the client. This returns
* 0 if the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
*/
int
auth_rsa(struct passwd *pw, BIGNUM *client_n)
@ -204,30 +211,32 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
/* Flag indicating whether authentication has succeeded. */
authenticated = 0;
/* Initialize mp-int variables. */
e = BN_new();
n = BN_new();
/* Go though the accepted keys, looking for the current key. If
found, perform a challenge-response dialog to verify that the
user really has the corresponding private key. */
/*
* Go though the accepted keys, looking for the current key. If
* found, perform a challenge-response dialog to verify that the
* user really has the corresponding private key.
*/
while (fgets(line, sizeof(line), f)) {
char *cp;
char *options;
linenum++;
/* Skip leading whitespace. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++);
/* Skip empty and comment lines. */
/* Skip leading whitespace, empty and comment lines. */
for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '\n' || *cp == '#')
continue;
/* Check if there are options for this key, and if so,
save their starting address and skip the option part
for now. If there are no options, set the starting
address to NULL. */
/*
* Check if there are options for this key, and if so,
* save their starting address and skip the option part
* for now. If there are no options, set the starting
* address to NULL.
*/
if (*cp < '0' || *cp > '9') {
int quoted = 0;
options = cp;
@ -258,7 +267,7 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
/* Check if the we have found the desired key (identified by its modulus). */
if (BN_cmp(n, client_n) != 0)
continue; /* Wrong key. */
continue;
/* We have found the desired key. */
@ -269,10 +278,12 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
packet_send_debug("Wrong response to RSA authentication challenge.");
continue;
}
/* Correct response. The client has been successfully
authenticated. Note that we have not yet processed the
options; this will be reset if the options cause the
authentication to be rejected. */
/*
* Correct response. The client has been successfully
* authenticated. Note that we have not yet processed the
* options; this will be reset if the options cause the
* authentication to be rejected.
*/
authenticated = 1;
/* RSA part of authentication was accepted. Now process the options. */
@ -412,7 +423,6 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
goto next_option;
}
bad_option:
/* Unknown option. */
log("Bad options in %.100s file, line %lu: %.50s",
SSH_USER_PERMITTED_KEYS, linenum, options);
packet_send_debug("Bad options in %.100s file, line %lu: %.50s",
@ -421,12 +431,14 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
break;
next_option:
/* Skip the comma, and move to the next option
(or break out if there are no more). */
/*
* Skip the comma, and move to the next option
* (or break out if there are no more).
*/
if (!*options)
fatal("Bugs in auth-rsa.c option processing.");
if (*options == ' ' || *options == '\t')
break; /* End of options. */
break; /* End of options. */
if (*options != ',')
goto bad_option;
options++;
@ -434,8 +446,10 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
continue;
}
}
/* Break out of the loop if authentication was successful;
otherwise continue searching. */
/*
* Break out of the loop if authentication was successful;
* otherwise continue searching.
*/
if (authenticated)
break;
}
@ -446,7 +460,6 @@ auth_rsa(struct passwd *pw, BIGNUM *client_n)
/* Close the file. */
fclose(f);
/* Clear any mp-int variables. */
BN_clear_free(n);
BN_clear_free(e);

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

@ -1,11 +1,15 @@
#include "includes.h"
#ifdef SKEY
RCSID("$Id: auth-skey.c,v 1.3 1999/11/23 22:25:52 markus Exp $");
#include "ssh.h"
#include <sha1.h>
#ifdef HAVE_OPENSSL
#include <openssl/sha1.h>
#endif
#ifdef HAVE_SSL
#include <ssl/sha1.h>
#endif
/* from %OpenBSD: skeylogin.c,v 1.32 1999/08/16 14:46:56 millert Exp % */

127
authfd.c
Просмотреть файл

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: authfd.c,v 1.7 1999/11/24 13:26:21 damien Exp $");
RCSID("$Id: authfd.c,v 1.8 1999/11/25 00:54:57 damien Exp $");
#include "ssh.h"
#include "rsa.h"
@ -63,9 +63,11 @@ ssh_get_authentication_socket()
return sock;
}
/* Closes the agent socket if it should be closed (depends on how it was
obtained). The argument must have been returned by
ssh_get_authentication_socket(). */
/*
* Closes the agent socket if it should be closed (depends on how it was
* obtained). The argument must have been returned by
* ssh_get_authentication_socket().
*/
void
ssh_close_authentication_socket(int sock)
@ -74,11 +76,13 @@ ssh_close_authentication_socket(int sock)
close(sock);
}
/* Opens and connects a private socket for communication with the
authentication agent. Returns the file descriptor (which must be
shut down and closed by the caller when no longer needed).
Returns NULL if an error occurred and the connection could not be
opened. */
/*
* Opens and connects a private socket for communication with the
* authentication agent. Returns the file descriptor (which must be
* shut down and closed by the caller when no longer needed).
* Returns NULL if an error occurred and the connection could not be
* opened.
*/
AuthenticationConnection *
ssh_get_authentication_connection()
@ -88,12 +92,13 @@ ssh_get_authentication_connection()
sock = ssh_get_authentication_socket();
/* Fail if we couldn't obtain a connection. This happens if we
exited due to a timeout. */
/*
* Fail if we couldn't obtain a connection. This happens if we
* exited due to a timeout.
*/
if (sock < 0)
return NULL;
/* Applocate the connection structure and initialize it. */
auth = xmalloc(sizeof(*auth));
auth->fd = sock;
buffer_init(&auth->packet);
@ -103,8 +108,10 @@ ssh_get_authentication_connection()
return auth;
}
/* Closes the connection to the authentication agent and frees any associated
memory. */
/*
* Closes the connection to the authentication agent and frees any associated
* memory.
*/
void
ssh_close_authentication_connection(AuthenticationConnection *ac)
@ -115,10 +122,12 @@ ssh_close_authentication_connection(AuthenticationConnection *ac)
xfree(ac);
}
/* Returns the first authentication identity held by the agent.
Returns true if an identity is available, 0 otherwise.
The caller must initialize the integers before the call, and free the
comment after a successful call (before calling ssh_get_next_identity). */
/*
* Returns the first authentication identity held by the agent.
* Returns true if an identity is available, 0 otherwise.
* The caller must initialize the integers before the call, and free the
* comment after a successful call (before calling ssh_get_next_identity).
*/
int
ssh_get_first_identity(AuthenticationConnection *auth,
@ -127,8 +136,10 @@ ssh_get_first_identity(AuthenticationConnection *auth,
unsigned char msg[8192];
int len, l;
/* Send a message to the agent requesting for a list of the
identities it can represent. */
/*
* Send a message to the agent requesting for a list of the
* identities it can represent.
*/
msg[0] = 0;
msg[1] = 0;
msg[2] = 0;
@ -149,8 +160,10 @@ ssh_get_first_identity(AuthenticationConnection *auth,
len -= l;
}
/* Extract the length, and check it for sanity. (We cannot trust
authentication agents). */
/*
* Extract the length, and check it for sanity. (We cannot trust
* authentication agents).
*/
len = GET_32BIT(msg);
if (len < 1 || len > 256 * 1024)
fatal("Authentication reply message too long: %d\n", len);
@ -182,10 +195,12 @@ ssh_get_first_identity(AuthenticationConnection *auth,
return ssh_get_next_identity(auth, e, n, comment);
}
/* Returns the next authentication identity for the agent. Other functions
can be called between this and ssh_get_first_identity or two calls of this
function. This returns 0 if there are no more identities. The caller
must free comment after a successful return. */
/*
* Returns the next authentication identity for the agent. Other functions
* can be called between this and ssh_get_first_identity or two calls of this
* function. This returns 0 if there are no more identities. The caller
* must free comment after a successful return.
*/
int
ssh_get_next_identity(AuthenticationConnection *auth,
@ -197,8 +212,10 @@ ssh_get_next_identity(AuthenticationConnection *auth,
if (auth->howmany <= 0)
return 0;
/* Get the next entry from the packet. These will abort with a
fatal error if the packet is too short or contains corrupt data. */
/*
* Get the next entry from the packet. These will abort with a fatal
* error if the packet is too short or contains corrupt data.
*/
bits = buffer_get_int(&auth->identities);
buffer_get_bignum(&auth->identities, e);
buffer_get_bignum(&auth->identities, n);
@ -214,11 +231,13 @@ ssh_get_next_identity(AuthenticationConnection *auth,
return 1;
}
/* Generates a random challenge, sends it to the agent, and waits for response
from the agent. Returns true (non-zero) if the agent gave the correct
answer, zero otherwise. Response type selects the style of response
desired, with 0 corresponding to protocol version 1.0 (no longer supported)
and 1 corresponding to protocol version 1.1. */
/*
* Generates a random challenge, sends it to the agent, and waits for
* response from the agent. Returns true (non-zero) if the agent gave the
* correct answer, zero otherwise. Response type selects the style of
* response desired, with 0 corresponding to protocol version 1.0 (no longer
* supported) and 1 corresponding to protocol version 1.1.
*/
int
ssh_decrypt_challenge(AuthenticationConnection *auth,
@ -259,8 +278,10 @@ error_cleanup:
buffer_free(&buffer);
return 0;
}
/* Wait for response from the agent. First read the length of the
response packet. */
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
len = 4;
while (len > 0) {
l = read(auth->fd, buf + 4 - len, len);
@ -303,8 +324,10 @@ error_cleanup:
if (buf[0] != SSH_AGENT_RSA_RESPONSE)
fatal("Bad authentication response: %d", buf[0]);
/* Get the response from the packet. This will abort with a fatal
error if the packet is corrupt. */
/*
* Get the response from the packet. This will abort with a fatal
* error if the packet is corrupt.
*/
for (i = 0; i < 16; i++)
response[i] = buffer_get_char(&buffer);
@ -315,8 +338,10 @@ error_cleanup:
return 1;
}
/* Adds an identity to the authentication server. This call is not meant to
be used by normal applications. */
/*
* Adds an identity to the authentication server. This call is not meant to
* be used by normal applications.
*/
int
ssh_add_identity(AuthenticationConnection *auth,
@ -401,8 +426,10 @@ error_cleanup:
return 0;
}
/* Removes an identity from the authentication server. This call is not meant
to be used by normal applications. */
/*
* Removes an identity from the authentication server. This call is not
* meant to be used by normal applications.
*/
int
ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
@ -431,8 +458,10 @@ error_cleanup:
buffer_free(&buffer);
return 0;
}
/* Wait for response from the agent. First read the length of the
response packet. */
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
len = 4;
while (len > 0) {
l = read(auth->fd, buf + 4 - len, len);
@ -480,8 +509,10 @@ error_cleanup:
return 0;
}
/* Removes all identities from the agent. This call is not meant
to be used by normal applications. */
/*
* Removes all identities from the agent. This call is not meant to be used
* by normal applications.
*/
int
ssh_remove_all_identities(AuthenticationConnection *auth)
@ -499,8 +530,10 @@ ssh_remove_all_identities(AuthenticationConnection *auth)
error("Error writing to authentication socket.");
return 0;
}
/* Wait for response from the agent. First read the length of the
response packet. */
/*
* Wait for response from the agent. First read the length of the
* response packet.
*/
len = 4;
while (len > 0) {
l = read(auth->fd, buf + 4 - len, len);

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

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: authfd.h,v 1.3 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: authfd.h,v 1.4 1999/11/25 00:54:58 damien Exp $"); */
#ifndef AUTHFD_H
#define AUTHFD_H
@ -40,33 +40,43 @@ typedef struct {
/* Returns the number of the authentication fd, or -1 if there is none. */
int ssh_get_authentication_socket();
/* This should be called for any descriptor returned by
ssh_get_authentication_socket(). Depending on the way the descriptor was
obtained, this may close the descriptor. */
/*
* This should be called for any descriptor returned by
* ssh_get_authentication_socket(). Depending on the way the descriptor was
* obtained, this may close the descriptor.
*/
void ssh_close_authentication_socket(int authfd);
/* Opens and connects a private socket for communication with the
authentication agent. Returns NULL if an error occurred and the
connection could not be opened. The connection should be closed by
the caller by calling ssh_close_authentication_connection(). */
/*
* Opens and connects a private socket for communication with the
* authentication agent. Returns NULL if an error occurred and the
* connection could not be opened. The connection should be closed by the
* caller by calling ssh_close_authentication_connection().
*/
AuthenticationConnection *ssh_get_authentication_connection();
/* Closes the connection to the authentication agent and frees any associated
memory. */
/*
* Closes the connection to the authentication agent and frees any associated
* memory.
*/
void ssh_close_authentication_connection(AuthenticationConnection * ac);
/* Returns the first authentication identity held by the agent.
Returns true if an identity is available, 0 otherwise.
The caller must initialize the integers before the call, and free the
comment after a successful call (before calling ssh_get_next_identity). */
/*
* Returns the first authentication identity held by the agent. Returns true
* if an identity is available, 0 otherwise. The caller must initialize the
* integers before the call, and free the comment after a successful call
* (before calling ssh_get_next_identity).
*/
int
ssh_get_first_identity(AuthenticationConnection * connection,
BIGNUM * e, BIGNUM * n, char **comment);
/* Returns the next authentication identity for the agent. Other functions
can be called between this and ssh_get_first_identity or two calls of this
function. This returns 0 if there are no more identities. The caller
must free comment after a successful return. */
/*
* Returns the next authentication identity for the agent. Other functions
* can be called between this and ssh_get_first_identity or two calls of this
* function. This returns 0 if there are no more identities. The caller
* must free comment after a successful return.
*/
int
ssh_get_next_identity(AuthenticationConnection * connection,
BIGNUM * e, BIGNUM * n, char **comment);
@ -80,24 +90,30 @@ ssh_decrypt_challenge(AuthenticationConnection * auth,
unsigned int response_type,
unsigned char response[16]);
/* Adds an identity to the authentication server. This call is not meant to
be used by normal applications. This returns true if the identity
was successfully added. */
int ssh_add_identity(AuthenticationConnection * connection,
RSA * key, const char *comment);
/*
* Adds an identity to the authentication server. This call is not meant to
* be used by normal applications. This returns true if the identity was
* successfully added.
*/
int
ssh_add_identity(AuthenticationConnection * connection, RSA * key,
const char *comment);
/* Removes the identity from the authentication server. This call is
not meant to be used by normal applications. This returns true if the
identity was successfully added. */
int ssh_remove_identity(AuthenticationConnection * connection,
RSA * key);
/*
* Removes the identity from the authentication server. This call is not
* meant to be used by normal applications. This returns true if the
* identity was successfully added.
*/
int ssh_remove_identity(AuthenticationConnection * connection, RSA * key);
/* Removes all identities from the authentication agent. This call is not
meant to be used by normal applications. This returns true if the
operation was successful. */
int ssh_remove_all_identities(AuthenticationConnection * connection);
/*
* Removes all identities from the authentication agent. This call is not
* meant to be used by normal applications. This returns true if the
* operation was successful.
*/
int ssh_remove_all_identities(AuthenticationConnection * connection);
/* Closes the connection to the authentication agent. */
void ssh_close_authentication(AuthenticationConnection * connection);
void ssh_close_authentication(AuthenticationConnection * connection);
#endif /* AUTHFD_H */

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

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: authfile.c,v 1.4 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: authfile.c,v 1.5 1999/11/25 00:54:58 damien Exp $");
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
@ -33,10 +33,12 @@ RCSID("$Id: authfile.c,v 1.4 1999/11/24 13:26:22 damien Exp $");
/* Version identification string for identity files. */
#define AUTHFILE_ID_STRING "SSH PRIVATE KEY FILE FORMAT 1.1\n"
/* Saves the authentication (private) key in a file, encrypting it with
passphrase. The identification of the file (lowest 64 bits of n)
will precede the key to provide identification of the key without
needing a passphrase. */
/*
* Saves the authentication (private) key in a file, encrypting it with
* passphrase. The identification of the file (lowest 64 bits of n) will
* precede the key to provide identification of the key without needing a
* passphrase.
*/
int
save_private_key(const char *filename, const char *passphrase,
@ -49,9 +51,10 @@ save_private_key(const char *filename, const char *passphrase,
int cipher_type;
u_int32_t rand;
/* If the passphrase is empty, use SSH_CIPHER_NONE to ease
converting to another cipher; otherwise use
SSH_AUTHFILE_CIPHER. */
/*
* If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
* to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
*/
if (strcmp(passphrase, "") == 0)
cipher_type = SSH_CIPHER_NONE;
else
@ -68,9 +71,11 @@ save_private_key(const char *filename, const char *passphrase,
buf[3] = buf[1];
buffer_append(&buffer, buf, 4);
/* Store the private key (n and e will not be stored because they
will be stored in plain text, and storing them also in
encrypted format would just give known plaintext). */
/*
* Store the private key (n and e will not be stored because they
* will be stored in plain text, and storing them also in encrypted
* format would just give known plaintext).
*/
buffer_put_bignum(&buffer, key->d);
buffer_put_bignum(&buffer, key->iqmp);
buffer_put_bignum(&buffer, key->q); /* reverse from SSL p */
@ -112,11 +117,9 @@ save_private_key(const char *filename, const char *passphrase,
memset(buf, 0, sizeof(buf));
buffer_free(&buffer);
/* Write to a file. */
f = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600);
if (f < 0)
return 0;
if (write(f, buffer_ptr(&encrypted), buffer_len(&encrypted)) !=
buffer_len(&encrypted)) {
debug("Write to key file %.200s failed: %.100s", filename,
@ -131,9 +134,11 @@ save_private_key(const char *filename, const char *passphrase,
return 1;
}
/* Loads the public part of the key file. Returns 0 if an error
was encountered (the file does not exist or is not readable), and
non-zero otherwise. */
/*
* Loads the public part of the key file. Returns 0 if an error was
* encountered (the file does not exist or is not readable), and non-zero
* otherwise.
*/
int
load_public_key(const char *filename, RSA * pub,
@ -144,11 +149,9 @@ load_public_key(const char *filename, RSA * pub,
Buffer buffer;
char *cp;
/* Read data from the file into the buffer. */
f = open(filename, O_RDONLY);
if (f < 0)
return 0;
len = lseek(f, (off_t) 0, SEEK_END);
lseek(f, (off_t) 0, SEEK_SET);
@ -170,8 +173,10 @@ load_public_key(const char *filename, RSA * pub,
buffer_free(&buffer);
return 0;
}
/* Make sure it begins with the id string. Consume the id string
from the buffer. */
/*
* Make sure it begins with the id string. Consume the id string
* from the buffer.
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);
@ -197,9 +202,12 @@ load_public_key(const char *filename, RSA * pub,
return 1;
}
/* Loads the private key from the file. Returns 0 if an error is encountered
(file does not exist or is not readable, or passphrase is bad).
This initializes the private key. */
/*
* Loads the private key from the file. Returns 0 if an error is encountered
* (file does not exist or is not readable, or passphrase is bad). This
* initializes the private key.
* Assumes we are called under uid of the owner of the file.
*/
int
load_private_key(const char *filename, const char *passphrase,
@ -214,12 +222,11 @@ load_private_key(const char *filename, const char *passphrase,
BIGNUM *aux;
struct stat st;
/* Read the file into the buffer. */
f = open(filename, O_RDONLY);
if (f < 0)
return 0;
/* We assume we are called under uid of the owner of the file */
/* check owner and modes */
if (fstat(f, &st) < 0 ||
(st.st_uid != 0 && st.st_uid != getuid()) ||
(st.st_mode & 077) != 0) {
@ -252,8 +259,10 @@ load_private_key(const char *filename, const char *passphrase,
buffer_free(&buffer);
return 0;
}
/* Make sure it begins with the id string. Consume the id string
from the buffer. */
/*
* Make sure it begins with the id string. Consume the id string
* from the buffer.
*/
for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)
if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {
debug("Bad key file %.200s.", filename);

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

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: bufaux.c,v 1.6 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: bufaux.c,v 1.7 1999/11/25 00:54:58 damien Exp $");
#include "ssh.h"
@ -54,7 +54,7 @@ buffer_put_bignum(Buffer *buffer, BIGNUM *value)
buffer_append(buffer, msg, 2);
/* Store the binary data. */
buffer_append(buffer, buf, oi);
/* Clear the temporary data. */
memset(buf, 0, bin_size);
xfree(buf);
}

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

@ -11,15 +11,17 @@
*
*/
/* RCSID("$Id: bufaux.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: bufaux.h,v 1.3 1999/11/25 00:54:58 damien Exp $"); */
#ifndef BUFAUX_H
#define BUFAUX_H
#include "buffer.h"
/* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
by (bits+7)/8 bytes of binary data, msb first. */
/*
* Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
* by (bits+7)/8 bytes of binary data, msb first.
*/
void buffer_put_bignum(Buffer * buffer, BIGNUM * value);
/* Retrieves an BIGNUM from the buffer. */
@ -37,12 +39,14 @@ int buffer_get_char(Buffer * buffer);
/* Stores a character in the buffer. */
void buffer_put_char(Buffer * buffer, int value);
/* Returns an arbitrary binary string from the buffer. The string cannot
be longer than 256k. The returned value points to memory allocated
with xmalloc; it is the responsibility of the calling function to free
the data. If length_ptr is non-NULL, the length of the returned data
will be stored there. A null character will be automatically appended
to the returned string, and is not counted in length. */
/*
* Returns an arbitrary binary string from the buffer. The string cannot be
* longer than 256k. The returned value points to memory allocated with
* xmalloc; it is the responsibility of the calling function to free the
* data. If length_ptr is non-NULL, the length of the returned data will be
* stored there. A null character will be automatically appended to the
* returned string, and is not counted in length.
*/
char *buffer_get_string(Buffer * buffer, unsigned int *length_ptr);
/* Stores and arbitrary binary string in the buffer. */

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

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: buffer.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: buffer.c,v 1.3 1999/11/25 00:54:58 damien Exp $");
#include "xmalloc.h"
#include "buffer.h"
@ -40,8 +40,10 @@ buffer_free(Buffer *buffer)
xfree(buffer->buf);
}
/* Clears any data from the buffer, making it empty. This does not actually
zero the memory. */
/*
* Clears any data from the buffer, making it empty. This does not actually
* zero the memory.
*/
void
buffer_clear(Buffer *buffer)
@ -60,9 +62,11 @@ buffer_append(Buffer *buffer, const char *data, unsigned int len)
memcpy(cp, data, len);
}
/* Appends space to the buffer, expanding the buffer if necessary.
This does not actually copy the data into the buffer, but instead
returns a pointer to the allocated region. */
/*
* Appends space to the buffer, expanding the buffer if necessary. This does
* not actually copy the data into the buffer, but instead returns a pointer
* to the allocated region.
*/
void
buffer_append_space(Buffer *buffer, char **datap, unsigned int len)
@ -79,8 +83,10 @@ restart:
buffer->end += len;
return;
}
/* If the buffer is quite empty, but all data is at the end, move
the data to the beginning and retry. */
/*
* If the buffer is quite empty, but all data is at the end, move the
* data to the beginning and retry.
*/
if (buffer->offset > buffer->alloc / 2) {
memmove(buffer->buf, buffer->buf + buffer->offset,
buffer->end - buffer->offset);

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

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: buffer.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: buffer.h,v 1.3 1999/11/25 00:54:58 damien Exp $"); */
#ifndef BUFFER_H
#define BUFFER_H
@ -37,9 +37,11 @@ void buffer_clear(Buffer * buffer);
/* Appends data to the buffer, expanding it if necessary. */
void buffer_append(Buffer * buffer, const char *data, unsigned int len);
/* Appends space to the buffer, expanding the buffer if necessary.
This does not actually copy the data into the buffer, but instead
returns a pointer to the allocated region. */
/*
* Appends space to the buffer, expanding the buffer if necessary. This does
* not actually copy the data into the buffer, but instead returns a pointer
* to the allocated region.
*/
void buffer_append_space(Buffer * buffer, char **datap, unsigned int len);
/* Returns the number of bytes of data in the buffer. */
@ -57,8 +59,10 @@ void buffer_consume_end(Buffer * buffer, unsigned int bytes);
/* Returns a pointer to the first used byte in the buffer. */
char *buffer_ptr(Buffer * buffer);
/* Dumps the contents of the buffer to stderr in hex. This intended for
debugging purposes only. */
/*
* Dumps the contents of the buffer to stderr in hex. This intended for
* debugging purposes only.
*/
void buffer_dump(Buffer * buffer);
#endif /* BUFFER_H */

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

@ -14,14 +14,16 @@
*/
#include "includes.h"
RCSID("$Id: canohost.c,v 1.3 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: canohost.c,v 1.4 1999/11/25 00:54:58 damien Exp $");
#include "packet.h"
#include "xmalloc.h"
#include "ssh.h"
/* Return the canonical name of the host at the other end of the socket.
The caller should free the returned string with xfree. */
/*
* Return the canonical name of the host at the other end of the socket. The
* caller should free the returned string with xfree.
*/
char *
get_remote_hostname(int socket)
@ -52,19 +54,23 @@ get_remote_hostname(int socket)
else
strlcpy(name, hp->h_name, sizeof(name));
/* Convert it to all lowercase (which is expected by the
rest of this software). */
/*
* Convert it to all lowercase (which is expected by the rest
* of this software).
*/
for (i = 0; name[i]; i++)
if (isupper(name[i]))
name[i] = tolower(name[i]);
/* Map it back to an IP address and check that the given
address actually is an address of this host. This is
necessary because anyone with access to a name server
can define arbitrary names for an IP address. Mapping
from name to IP address can be trusted better (but can
still be fooled if the intruder has access to the name
server of the domain). */
/*
* Map it back to an IP address and check that the given
* address actually is an address of this host. This is
* necessary because anyone with access to a name server can
* define arbitrary names for an IP address. Mapping from
* name to IP address can be trusted better (but can still be
* fooled if the intruder has access to the name server of
* the domain).
*/
hp = gethostbyname(name);
if (!hp) {
log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
@ -76,8 +82,10 @@ get_remote_hostname(int socket)
if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))
== 0)
break;
/* If we reached the end of the list, the address was not
there. */
/*
* If we reached the end of the list, the address was not
* there.
*/
if (!hp->h_addr_list[i]) {
/* Address not found for the host name. */
log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
@ -94,16 +102,17 @@ get_remote_hostname(int socket)
check_ip_options:
/* If IP options are supported, make sure there are none (log and
disconnect them if any are found). Basically we are worried
about source routing; it can be used to pretend you are
somebody (ip-address) you are not. That itself may be "almost
acceptable" under certain circumstances, but rhosts
autentication is useless if source routing is accepted. Notice
also that if we just dropped source routing here, the other
side could use IP spoofing to do rest of the interaction and
could still bypass security. So we exit here if we detect any
IP options. */
/*
* If IP options are supported, make sure there are none (log and
* disconnect them if any are found). Basically we are worried about
* source routing; it can be used to pretend you are somebody
* (ip-address) you are not. That itself may be "almost acceptable"
* under certain circumstances, but rhosts autentication is useless
* if source routing is accepted. Notice also that if we just dropped
* source routing here, the other side could use IP spoofing to do
* rest of the interaction and could still bypass security. So we
* exit here if we detect any IP options.
*/
{
unsigned char options[200], *ucp;
char text[1024], *cp;
@ -134,9 +143,11 @@ check_ip_options:
static char *canonical_host_name = NULL;
static char *canonical_host_ip = NULL;
/* Return the canonical name of the host in the other side of the current
connection. The host name is cached, so it is efficient to call this
several times. */
/*
* Return the canonical name of the host in the other side of the current
* connection. The host name is cached, so it is efficient to call this
* several times.
*/
const char *
get_canonical_hostname()
@ -154,8 +165,10 @@ get_canonical_hostname()
return canonical_host_name;
}
/* Returns the IP-address of the remote host as a string. The returned
string need not be freed. */
/*
* Returns the IP-address of the remote host as a string. The returned
* string need not be freed.
*/
const char *
get_remote_ipaddr()
@ -163,7 +176,7 @@ get_remote_ipaddr()
struct sockaddr_in from;
int fromlen, socket;
/* Check if we have previously retrieved this same name. */
/* Check whether we have chached the name. */
if (canonical_host_ip != NULL)
return canonical_host_ip;
@ -215,8 +228,10 @@ get_remote_port()
{
int socket;
/* If the connection is not a socket, return 65535. This is
intentionally chosen to be an unprivileged port number. */
/*
* If the connection is not a socket, return 65535. This is
* intentionally chosen to be an unprivileged port number.
*/
if (packet_get_connection_in() != packet_get_connection_out())
return 65535;

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

@ -16,7 +16,7 @@
*/
#include "includes.h"
RCSID("$Id: channels.c,v 1.7 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: channels.c,v 1.8 1999/11/25 00:54:58 damien Exp $");
#include "ssh.h"
#include "packet.h"
@ -37,17 +37,23 @@ RCSID("$Id: channels.c,v 1.7 1999/11/24 13:26:22 damien Exp $");
/* Max len of agent socket */
#define MAX_SOCKET_NAME 100
/* Pointer to an array containing all allocated channels. The array is
dynamically extended as needed. */
/*
* Pointer to an array containing all allocated channels. The array is
* dynamically extended as needed.
*/
static Channel *channels = NULL;
/* Size of the channel array. All slots of the array must always be
initialized (at least the type field); unused slots are marked with
type SSH_CHANNEL_FREE. */
/*
* Size of the channel array. All slots of the array must always be
* initialized (at least the type field); unused slots are marked with type
* SSH_CHANNEL_FREE.
*/
static int channels_alloc = 0;
/* Maximum file descriptor value used in any of the channels. This is updated
in channel_allocate. */
/*
* Maximum file descriptor value used in any of the channels. This is
* updated in channel_allocate.
*/
static int channel_max_fd_value = 0;
/* Name and directory of socket for authentication agent forwarding. */
@ -61,15 +67,19 @@ char *x11_saved_proto = NULL;
char *x11_saved_data = NULL;
unsigned int x11_saved_data_len = 0;
/* Fake X11 authentication data. This is what the server will be sending
us; we should replace any occurrences of this by the real data. */
/*
* Fake X11 authentication data. This is what the server will be sending us;
* we should replace any occurrences of this by the real data.
*/
char *x11_fake_data = NULL;
unsigned int x11_fake_data_len;
/* Data structure for storing which hosts are permitted for forward requests.
The local sides of any remote forwards are stored in this array to prevent
a corrupt remote server from accessing arbitrary TCP/IP ports on our
local network (which might be behind a firewall). */
/*
* Data structure for storing which hosts are permitted for forward requests.
* The local sides of any remote forwards are stored in this array to prevent
* a corrupt remote server from accessing arbitrary TCP/IP ports on our local
* network (which might be behind a firewall).
*/
typedef struct {
char *host; /* Host name. */
int port; /* Port number. */
@ -79,9 +89,11 @@ typedef struct {
static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];
/* Number of permitted host/port pairs in the array. */
static int num_permitted_opens = 0;
/* If this is true, all opens are permitted. This is the case on the
server on which we have to trust the client anyway, and the user could
do anything after logging in anyway. */
/*
* If this is true, all opens are permitted. This is the case on the server
* on which we have to trust the client anyway, and the user could do
* anything after logging in anyway.
*/
static int all_opens_permitted = 0;
/* This is set to true if both sides support SSH_PROTOFLAG_HOST_IN_FWD_OPEN. */
@ -95,9 +107,11 @@ channel_set_options(int hostname_in_open)
have_hostname_in_open = hostname_in_open;
}
/* 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. */
/*
* 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()
@ -105,8 +119,10 @@ channel_permit_all_opens()
all_opens_permitted = 1;
}
/* Allocate a new channel object and set its type and socket.
This will cause remote_name to be freed. */
/*
* Allocate a new channel object and set its type and socket. This will cause
* remote_name to be freed.
*/
int
channel_allocate(int type, int sock, char *remote_name)
@ -117,6 +133,7 @@ channel_allocate(int type, int sock, char *remote_name)
/* Update the maximum file descriptor value. */
if (sock > channel_max_fd_value)
channel_max_fd_value = sock;
/* XXX set close-on-exec -markus */
/* Do initial allocation if this is the first call. */
if (channels_alloc == 0) {
@ -124,9 +141,10 @@ channel_allocate(int type, int sock, char *remote_name)
channels = xmalloc(channels_alloc * sizeof(Channel));
for (i = 0; i < channels_alloc; i++)
channels[i].type = SSH_CHANNEL_FREE;
/* Kludge: arrange a call to channel_stop_listening if we
terminate with fatal(). */
/*
* Kludge: arrange a call to channel_stop_listening if we
* terminate with fatal().
*/
fatal_add_cleanup((void (*) (void *)) channel_stop_listening, NULL);
}
/* Try to find a free slot where to put the new channel. */
@ -137,8 +155,7 @@ channel_allocate(int type, int sock, char *remote_name)
break;
}
if (found == -1) {
/* There are no free slots. Take last+1 slot and expand
the array. */
/* There are no free slots. Take last+1 slot and expand the array. */
found = channels_alloc;
channels_alloc += 10;
debug("channel: expanding %d", channels_alloc);
@ -181,8 +198,10 @@ channel_free(int channel)
}
}
/* This is called just before select() to add any bits relevant to
channels in the select bitmasks. */
/*
* This is called just before select() to add any bits relevant to channels
* in the select bitmasks.
*/
void
channel_prepare_select(fd_set * readset, fd_set * writeset)
@ -248,15 +267,16 @@ redo:
break;
case SSH_CHANNEL_X11_OPEN:
/* This is a special state for X11 authentication
spoofing. An opened X11 connection (when
authentication spoofing is being done) remains
in this state until the first packet has been
completely read. The authentication data in
that packet is then substituted by the real
data if it matches the fake data, and the
channel is put into normal mode. */
/*
* This is a special state for X11 authentication
* spoofing. An opened X11 connection (when
* authentication spoofing is being done) remains in
* this state until the first packet has been
* completely read. The authentication data in that
* packet is then substituted by the real data if it
* matches the fake data, and the channel is put into
* normal mode.
*/
/* Check if the fixed size part of the packet is in buffer. */
if (buffer_len(&ch->output) < 12)
break;
@ -303,9 +323,11 @@ redo:
ch->type = SSH_CHANNEL_OPEN;
goto reject;
}
/* Received authentication protocol and data match
our fake data. Substitute the fake data with
real data. */
/*
* Received authentication protocol and data match
* our fake data. Substitute the fake data with real
* data.
*/
memcpy(ucp + 12 + ((proto_len + 3) & ~3),
x11_saved_data, x11_saved_data_len);
@ -314,8 +336,10 @@ redo:
goto redo;
reject:
/* We have received an X11 connection that has bad
authentication information. */
/*
* We have received an X11 connection that has bad
* authentication information.
*/
log("X11 connection rejected because of wrong authentication.\r\n");
buffer_clear(&ch->input);
buffer_clear(&ch->output);
@ -341,8 +365,10 @@ redo:
}
}
/* After select, perform any appropriate operations for channels which
have events pending. */
/*
* After select, perform any appropriate operations for channels which have
* events pending.
*/
void
channel_after_select(fd_set * readset, fd_set * writeset)
@ -381,8 +407,10 @@ channel_after_select(fd_set * readset, fd_set * writeset)
break;
case SSH_CHANNEL_PORT_LISTENER:
/* This socket is listening for connections to a
forwarded TCP/IP port. */
/*
* This socket is listening for connections to a
* forwarded TCP/IP port.
*/
if (FD_ISSET(ch->sock, readset)) {
debug("Connection to port %d forwarding to %.100s:%d requested.",
ch->listening_port, ch->path, ch->host_port);
@ -410,8 +438,10 @@ channel_after_select(fd_set * readset, fd_set * writeset)
break;
case SSH_CHANNEL_AUTH_SOCKET:
/* This is the authentication agent socket
listening for connections from clients. */
/*
* This is the authentication agent socket listening
* for connections from clients.
*/
if (FD_ISSET(ch->sock, readset)) {
int nchan;
len = sizeof(addr);
@ -429,13 +459,16 @@ channel_after_select(fd_set * readset, fd_set * writeset)
break;
case SSH_CHANNEL_OPEN:
/* This is an open two-way communication channel.
It is not of interest to us at this point what
kind of data is being transmitted. */
/*
* This is an open two-way communication channel. It
* is not of interest to us at this point what kind
* of data is being transmitted.
*/
/* Read available incoming data and append it to
buffer; shutdown socket, if read or write
failes */
/*
* Read available incoming data and append it to
* buffer; shutdown socket, if read or write failes
*/
if (FD_ISSET(ch->sock, readset)) {
len = read(ch->sock, buf, sizeof(buf));
if (len <= 0) {
@ -500,8 +533,7 @@ channel_output_poll()
for (i = 0; i < channels_alloc; i++) {
ch = &channels[i];
/* We are only interested in channels that can have
buffered incoming data. */
/* We are only interested in channels that can have buffered incoming data. */
if (ch->type != SSH_CHANNEL_OPEN &&
ch->type != SSH_CHANNEL_INPUT_DRAINING)
continue;
@ -509,8 +541,7 @@ channel_output_poll()
/* Get the amount of buffered data for this channel. */
len = buffer_len(&ch->input);
if (len > 0) {
/* Send some data for the other side over the
secure connection. */
/* Send some data for the other side over the secure connection. */
if (packet_is_interactive()) {
if (len > 1024)
len = 512;
@ -527,17 +558,20 @@ channel_output_poll()
} else if (ch->istate == CHAN_INPUT_WAIT_DRAIN) {
if (compat13)
fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3");
/* input-buffer is empty and read-socket shutdown:
tell peer, that we will not send more data:
send IEOF */
/*
* input-buffer is empty and read-socket shutdown:
* tell peer, that we will not send more data: send IEOF
*/
chan_ibuf_empty(ch);
}
}
}
/* 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. */
/*
* 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)
@ -564,8 +598,10 @@ channel_input_data(int payload_len)
xfree(data);
}
/* Returns true if no channel has too much buffered data, and false if
one or more channel is overfull. */
/*
* Returns true if no channel has too much buffered data, and false if one or
* more channel is overfull.
*/
int
channel_not_very_much_buffered_data()
@ -615,20 +651,27 @@ channel_input_close()
chan_rcvd_ieof(&channels[channel]);
return;
}
/* Send a confirmation that we have closed the channel and no more
data is coming for it. */
/*
* Send a confirmation that we have closed the channel and no more
* data is coming for it.
*/
packet_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION);
packet_put_int(channels[channel].remote_id);
packet_send();
/* If the channel is in closed state, we have sent a close
request, and the other side will eventually respond with a
confirmation. Thus, we cannot free the channel here, because
then there would be no-one to receive the confirmation. The
channel gets freed when the confirmation arrives. */
/*
* If the channel is in closed state, we have sent a close request,
* and the other side will eventually respond with a confirmation.
* Thus, we cannot free the channel here, because then there would be
* no-one to receive the confirmation. The channel gets freed when
* the confirmation arrives.
*/
if (channels[channel].type != SSH_CHANNEL_CLOSED) {
/* Not a closed channel - mark it as draining, which will
cause it to be freed later. */
/*
* Not a closed channel - mark it as draining, which will
* cause it to be freed later.
*/
buffer_consume(&channels[channel].input,
buffer_len(&channels[channel].input));
channels[channel].type = SSH_CHANNEL_OUTPUT_DRAINING;
@ -678,8 +721,7 @@ channel_input_open_confirmation()
/* Get remote side's id for this channel. */
remote_channel = packet_get_int();
/* Record the remote channel number and mark that the channel is
now open. */
/* Record the remote channel number and mark that the channel is now open. */
channels[channel].remote_id = remote_channel;
channels[channel].type = SSH_CHANNEL_OPEN;
}
@ -702,8 +744,10 @@ channel_input_open_failure()
channel_free(channel);
}
/* Stops listening for channels, and removes any unix domain sockets that
we might have. */
/*
* Stops listening for channels, and removes any unix domain sockets that we
* might have.
*/
void
channel_stop_listening()
@ -727,8 +771,10 @@ channel_stop_listening()
}
}
/* Closes the sockets of all channels. This is used to close extra file
descriptors after a fork. */
/*
* Closes the sockets of all channels. This is used to close extra file
* descriptors after a fork.
*/
void
channel_close_all()
@ -778,9 +824,11 @@ channel_still_open()
return 0;
}
/* Returns a message describing the currently open forwarded
connections, suitable for sending to the client. The message
contains crlf pairs for newlines. */
/*
* Returns a message describing the currently open forwarded connections,
* suitable for sending to the client. The message contains crlf pairs for
* newlines.
*/
char *
channel_open_message()
@ -822,16 +870,19 @@ channel_open_message()
return cp;
}
/* Initiate forwarding of connections to local port "port" through the secure
channel to host:port from remote side. */
/*
* Initiate forwarding of connections to local port "port" through the secure
* channel to host:port from remote side.
*/
void
channel_request_local_forwarding(int port, const char *host,
int host_port)
{
int ch, sock;
int ch, sock, on = 1;
struct sockaddr_in sin;
extern Options options;
struct linger linger;
if (strlen(host) > sizeof(channels[0].path) - 1)
packet_disconnect("Forward host name too long.");
@ -850,6 +901,15 @@ channel_request_local_forwarding(int port, const char *host,
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sin.sin_port = htons(port);
/*
* Set socket options. We would like the socket to disappear as soon
* as it has been closed for whatever reason.
*/
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on));
linger.l_onoff = 1;
linger.l_linger = 5;
setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
/* Bind the socket to the address. */
if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
packet_disconnect("bind: %.100s", strerror(errno));
@ -866,8 +926,10 @@ channel_request_local_forwarding(int port, const char *host,
channels[ch].listening_port = port;
}
/* Initiate forwarding of connections to port "port" on remote host through
the secure channel to host:port from local side. */
/*
* Initiate forwarding of connections to port "port" on remote host through
* the secure channel to host:port from local side.
*/
void
channel_request_remote_forwarding(int port, const char *host,
@ -890,15 +952,18 @@ channel_request_remote_forwarding(int port, const char *host,
packet_send();
packet_write_wait();
/* Wait for response from the remote side. It will send a
disconnect message on failure, and we will never see it here. */
/*
* Wait for response from the remote side. It will send a disconnect
* message on failure, and we will never see it here.
*/
packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
}
/* 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. */
/*
* 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)
@ -915,8 +980,10 @@ channel_input_port_forward_request(int is_root)
if ((port & 0xffff) != port)
packet_disconnect("Requested forwarding of nonexistent port %d.", port);
/* Check that an unprivileged user is not trying to forward a
privileged port. */
/*
* Check that an unprivileged user is not trying to forward a
* privileged port.
*/
if (port < IPPORT_RESERVED && !is_root)
packet_disconnect("Requested forwarding of port %d but user is not root.",
port);
@ -928,9 +995,11 @@ channel_input_port_forward_request(int is_root)
xfree(hostname);
}
/* 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. */
/*
* 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)
@ -951,13 +1020,16 @@ channel_input_port_open(int payload_len)
host_port = packet_get_int();
/* Get remote originator name. */
if (have_hostname_in_open)
if (have_hostname_in_open) {
originator_string = packet_get_string(&originator_len);
else
originator_len += 4; /* size of packet_int */
} else {
originator_string = xstrdup("unknown (remote did not supply name)");
originator_len = 0; /* no originator supplied */
}
packet_integrity_check(payload_len,
4 + 4 + host_len + 4 + 4 + originator_len,
4 + 4 + host_len + 4 + originator_len,
SSH_MSG_PORT_OPEN);
/* Check if opening that port is permitted. */
@ -1040,9 +1112,11 @@ fail:
packet_send();
}
/* Creates an internet domain socket for listening for X11 connections.
Returns a suitable value for the DISPLAY variable, or NULL if an error
occurs. */
/*
* 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_number)
@ -1134,9 +1208,11 @@ connect_local_xsocket(unsigned dnr)
}
/* 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. */
/*
* 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)
@ -1152,13 +1228,16 @@ x11_input_open(int payload_len)
remote_channel = packet_get_int();
/* Get remote originator name. */
if (have_hostname_in_open)
if (have_hostname_in_open) {
remote_host = packet_get_string(&remote_len);
else
remote_len += 4;
} else {
remote_host = xstrdup("unknown (remote did not supply name)");
remote_len = 0;
}
debug("Received X11 open request.");
packet_integrity_check(payload_len, 4 + 4 + remote_len, SSH_SMSG_X11_OPEN);
packet_integrity_check(payload_len, 4 + remote_len, SSH_SMSG_X11_OPEN);
/* Try to open a socket for the local X server. */
display = getenv("DISPLAY");
@ -1166,11 +1245,15 @@ x11_input_open(int payload_len)
error("DISPLAY not set.");
goto fail;
}
/* Now we decode the value of the DISPLAY variable and make a
connection to the real X server. */
/*
* Now we decode the value of the DISPLAY variable and make a
* connection to the real X server.
*/
/* Check if it is a unix domain socket. Unix domain displays are
in one of the following formats: unix:d[.s], :d[.s], ::d[.s] */
/*
* Check if it is a unix domain socket. Unix domain displays are in
* one of the following formats: unix:d[.s], :d[.s], ::d[.s]
*/
if (strncmp(display, "unix:", 5) == 0 ||
display[0] == ':') {
/* Connect to the unix domain socket. */
@ -1187,8 +1270,10 @@ x11_input_open(int payload_len)
/* OK, we now have a connection to the display. */
goto success;
}
/* Connect to an inet socket. The DISPLAY value is supposedly
hostname:d[.s], where hostname may also be numeric IP address. */
/*
* Connect to an inet socket. The DISPLAY value is supposedly
* hostname:d[.s], where hostname may also be numeric IP address.
*/
strncpy(buf, display, sizeof(buf));
buf[sizeof(buf) - 1] = 0;
cp = strchr(buf, ':');
@ -1197,8 +1282,7 @@ x11_input_open(int payload_len)
goto fail;
}
*cp = 0;
/* buf now contains the host name. But first we parse the display
number. */
/* buf now contains the host name. But first we parse the display number. */
if (sscanf(cp + 1, "%d", &display_number) != 1) {
error("Could not parse display number from DISPLAY: %.100s",
display);
@ -1267,8 +1351,10 @@ fail:
packet_send();
}
/* Requests forwarding of X11 connections, generates fake authentication
data, and enables authentication spoofing. */
/*
* Requests forwarding of X11 connections, generates fake authentication
* data, and enables authentication spoofing.
*/
void
x11_request_forwarding_with_spoofing(const char *proto, const char *data)
@ -1293,8 +1379,10 @@ x11_request_forwarding_with_spoofing(const char *proto, const char *data)
/* Save protocol name. */
x11_saved_proto = xstrdup(proto);
/* Extract real authentication data and generate fake data of the
same length. */
/*
* Extract real authentication data and generate fake data of the
* same length.
*/
x11_saved_data = xmalloc(data_len);
x11_fake_data = xmalloc(data_len);
for (i = 0; i < data_len; i++) {
@ -1334,9 +1422,11 @@ auth_request_forwarding()
packet_write_wait();
}
/* Returns the name of the forwarded authentication socket. Returns NULL
if there is no forwarded authentication socket. The returned value
points to a static buffer. */
/*
* 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()
@ -1353,8 +1443,10 @@ cleanup_socket(void)
rmdir(channel_forwarded_auth_socket_dir);
}
/* This if called to process SSH_CMSG_AGENT_REQUEST_FORWARDING on the server.
This starts forwarding authentication requests. */
/*
* 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)
@ -1422,14 +1514,18 @@ auth_input_open_request()
/* Read the remote channel number from the message. */
remch = packet_get_int();
/* Get a connection to the local authentication agent (this may
again get forwarded). */
/*
* Get a connection to the local authentication agent (this may again
* get forwarded).
*/
sock = ssh_get_authentication_socket();
/* If we could not connect the agent, send an error message back
to the server. This should never happen unless the agent dies,
because authentication forwarding is only enabled if we have an
agent. */
/*
* If we could not connect the agent, send an error message back to
* the server. This should never happen unless the agent dies,
* because authentication forwarding is only enabled if we have an
* agent.
*/
if (sock < 0) {
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(remch);
@ -1438,9 +1534,11 @@ auth_input_open_request()
}
debug("Forwarding authentication connection.");
/* Dummy host name. This will be freed when the channel is freed;
it will still be valid in the packet_put_string below since the
channel cannot yet be freed at that point. */
/*
* Dummy host name. This will be freed when the channel is freed; it
* will still be valid in the packet_put_string below since the
* channel cannot yet be freed at that point.
*/
dummyname = xstrdup("authentication agent connection");
newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname);

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

@ -1,29 +1,26 @@
/* RCSID("$Id: channels.h,v 1.3 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: channels.h,v 1.4 1999/11/25 00:54:58 damien Exp $"); */
#ifndef CHANNELS_H
#define CHANNELS_H
/* Definitions for channel types. */
#define SSH_CHANNEL_FREE 0 /* This channel is free
* (unused). */
#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11
* conn. */
#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */
#define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */
#define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */
#define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */
#define SSH_CHANNEL_OPEN 4 /* normal open two-way channel */
#define SSH_CHANNEL_CLOSED 5 /* waiting for close
* confirmation */
/* SSH_CHANNEL_AUTH_FD 6 authentication fd */
#define SSH_CHANNEL_CLOSED 5 /* waiting for close confirmation */
/* SSH_CHANNEL_AUTH_FD 6 authentication fd */
#define SSH_CHANNEL_AUTH_SOCKET 7 /* authentication socket */
/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */
/* SSH_CHANNEL_AUTH_SOCKET_FD 8 connection to auth socket */
#define SSH_CHANNEL_X11_OPEN 9 /* reading first X11 packet */
#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to
* conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to
* app */
#define SSH_CHANNEL_INPUT_DRAINING 10 /* sending remaining data to conn */
#define SSH_CHANNEL_OUTPUT_DRAINING 11 /* sending remaining data to app */
/* Data structure for channel data. This is iniailized in channel_allocate
and cleared in channel_free. */
/*
* Data structure for channel data. This is iniailized in channel_allocate
* and cleared in channel_free.
*/
typedef struct Channel {
int type; /* channel type/state */

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

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$Id: cipher.c,v 1.7 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: cipher.c,v 1.8 1999/11/25 00:54:58 damien Exp $");
#include "ssh.h"
#include "cipher.h"
@ -121,8 +121,10 @@ detect_cbc_attack(const unsigned char *src,
cipher_attack_detected("CRC-32 CBC insertion attack detected");
}
/* Names of all encryption algorithms. These must match the numbers defined
int cipher.h. */
/*
* Names of all encryption algorithms.
* These must match the numbers defined in cipher.h.
*/
static char *cipher_names[] =
{
"none",
@ -134,9 +136,11 @@ static char *cipher_names[] =
"blowfish"
};
/* Returns a bit mask indicating which ciphers are supported by this
implementation. The bit mask has the corresponding bit set of each
supported cipher. */
/*
* Returns a bit mask indicating which ciphers are supported by this
* implementation. The bit mask has the corresponding bit set of each
* supported cipher.
*/
unsigned int
cipher_mask()
@ -158,8 +162,10 @@ cipher_name(int cipher)
return cipher_names[cipher];
}
/* Parses the name of the cipher. Returns the number of the corresponding
cipher, or -1 on error. */
/*
* Parses the name of the cipher. Returns the number of the corresponding
* cipher, or -1 on error.
*/
int
cipher_number(const char *name)
@ -172,8 +178,10 @@ cipher_number(const char *name)
return -1;
}
/* Selects the cipher, and keys if by computing the MD5 checksum of the
passphrase and using the resulting 16 bytes as the key. */
/*
* Selects the cipher, and keys if by computing the MD5 checksum of the
* passphrase and using the resulting 16 bytes as the key.
*/
void
cipher_set_key_string(CipherContext *context, int cipher,
@ -211,15 +219,18 @@ cipher_set_key(CipherContext *context, int cipher,
/* Initialize the initialization vector. */
switch (cipher) {
case SSH_CIPHER_NONE:
/* Has to stay for authfile saving of private key with
no passphrase */
/*
* Has to stay for authfile saving of private key with no
* passphrase
*/
break;
case SSH_CIPHER_3DES:
/* Note: the least significant bit of each byte of key is
parity, and must be ignored by the implementation. 16
bytes of key are used (first and last keys are the
same). */
/*
* Note: the least significant bit of each byte of key is
* parity, and must be ignored by the implementation. 16
* bytes of key are used (first and last keys are the same).
*/
if (keylen < 16)
error("Key length %d is insufficient for 3DES.", keylen);
des_set_key((void *) padded, context->u.des3.key1);

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

@ -11,7 +11,7 @@
*
*/
/* RCSID("$Id: cipher.h,v 1.4 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: cipher.h,v 1.5 1999/11/25 00:54:58 damien Exp $"); */
#ifndef CIPHER_H
#define CIPHER_H
@ -54,26 +54,34 @@ typedef struct {
} bf;
} u;
} CipherContext;
/* Returns a bit mask indicating which ciphers are supported by this
implementation. The bit mask has the corresponding bit set of each
supported cipher. */
/*
* Returns a bit mask indicating which ciphers are supported by this
* implementation. The bit mask has the corresponding bit set of each
* supported cipher.
*/
unsigned int cipher_mask();
/* Returns the name of the cipher. */
const char *cipher_name(int cipher);
/* Parses the name of the cipher. Returns the number of the corresponding
cipher, or -1 on error. */
/*
* Parses the name of the cipher. Returns the number of the corresponding
* cipher, or -1 on error.
*/
int cipher_number(const char *name);
/* Selects the cipher to use and sets the key. If for_encryption is true,
the key is setup for encryption; otherwise it is setup for decryption. */
/*
* Selects the cipher to use and sets the key. If for_encryption is true,
* the key is setup for encryption; otherwise it is setup for decryption.
*/
void
cipher_set_key(CipherContext * context, int cipher,
const unsigned char *key, int keylen, int for_encryption);
/* Sets key for the cipher by computing the MD5 checksum of the passphrase,
and using the resulting 16 bytes as the key. */
/*
* Sets key for the cipher by computing the MD5 checksum of the passphrase,
* and using the resulting 16 bytes as the key.
*/
void
cipher_set_key_string(CipherContext * context, int cipher,
const char *passphrase, int for_encryption);
@ -88,8 +96,10 @@ void
cipher_decrypt(CipherContext * context, unsigned char *dest,
const unsigned char *src, unsigned int len);
/* If and CRC-32 attack is detected this function is called. Defaults
* to fatal, changed to packet_disconnect in sshd and ssh. */
extern void (*cipher_attack_detected) (const char *fmt,...);
/*
* If and CRC-32 attack is detected this function is called. Defaults to
* fatal, changed to packet_disconnect in sshd and ssh.
*/
extern void (*cipher_attack_detected) (const char *fmt, ...);
#endif /* CIPHER_H */

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

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: clientloop.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: clientloop.c,v 1.6 1999/11/25 00:54:58 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -27,22 +27,28 @@ RCSID("$Id: clientloop.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
/* Flag indicating that stdin should be redirected from /dev/null. */
extern int stdin_null_flag;
/* Name of the host we are connecting to. This is the name given on the
command line, or the HostName specified for the user-supplied name
in a configuration file. */
/*
* Name of the host we are connecting to. This is the name given on the
* command line, or the HostName specified for the user-supplied name in a
* configuration file.
*/
extern char *host;
/* Flag to indicate that we have received a window change signal which has
not yet been processed. This will cause a message indicating the new
window size to be sent to the server a little later. This is volatile
because this is updated in a signal handler. */
/*
* Flag to indicate that we have received a window change signal which has
* not yet been processed. This will cause a message indicating the new
* window size to be sent to the server a little later. This is volatile
* because this is updated in a signal handler.
*/
static volatile int received_window_change_signal = 0;
/* Terminal modes, as saved by enter_raw_mode. */
static struct termios saved_tio;
/* Flag indicating whether we are in raw mode. This is used by enter_raw_mode
and leave_raw_mode. */
/*
* Flag indicating whether we are in raw mode. This is used by
* enter_raw_mode and leave_raw_mode.
*/
static int in_raw_mode = 0;
/* Flag indicating whether the user\'s terminal is in non-blocking mode. */
@ -64,8 +70,7 @@ static unsigned long stdin_bytes, stdout_bytes, stderr_bytes;
static int quit_pending; /* Set to non-zero to quit the client loop. */
static int escape_char; /* Escape character. */
/* Returns the user\'s terminal to normal mode if it had been put in raw
mode. */
/* Returns the user\'s terminal to normal mode if it had been put in raw mode. */
void
leave_raw_mode()
@ -127,8 +132,10 @@ enter_non_blocking()
fatal_add_cleanup((void (*) (void *)) leave_non_blocking, NULL);
}
/* Signal handler for the window change signal (SIGWINCH). This just
sets a flag indicating that the window has changed. */
/*
* Signal handler for the window change signal (SIGWINCH). This just sets a
* flag indicating that the window has changed.
*/
void
window_change_handler(int sig)
@ -137,8 +144,10 @@ window_change_handler(int sig)
signal(SIGWINCH, window_change_handler);
}
/* Signal handler for signals that cause the program to terminate. These
signals must be trapped to restore terminal modes. */
/*
* Signal handler for signals that cause the program to terminate. These
* signals must be trapped to restore terminal modes.
*/
void
signal_handler(int sig)
@ -152,8 +161,10 @@ signal_handler(int sig)
fatal("Killed by signal %d.", sig);
}
/* Returns current time in seconds from Jan 1, 1970 with the maximum available
resolution. */
/*
* Returns current time in seconds from Jan 1, 1970 with the maximum
* available resolution.
*/
double
get_current_time()
@ -163,9 +174,11 @@ get_current_time()
return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0;
}
/* This is called when the interactive is entered. This checks if there
is an EOF coming on stdin. We must check this explicitly, as select()
does not appear to wake up when redirecting from /dev/null. */
/*
* This is called when the interactive is entered. This checks if there is
* an EOF coming on stdin. We must check this explicitly, as select() does
* not appear to wake up when redirecting from /dev/null.
*/
void
client_check_initial_eof_on_stdin()
@ -173,13 +186,14 @@ client_check_initial_eof_on_stdin()
int len;
char buf[1];
/* If standard input is to be "redirected from /dev/null", we
simply mark that we have seen an EOF and send an EOF message to
the server. Otherwise, we try to read a single character; it
appears that for some files, such /dev/null, select() never
wakes up for read for this descriptor, which means that we
never get EOF. This way we will get the EOF if stdin comes
from /dev/null or similar. */
/*
* If standard input is to be "redirected from /dev/null", we simply
* mark that we have seen an EOF and send an EOF message to the
* server. Otherwise, we try to read a single character; it appears
* that for some files, such /dev/null, select() never wakes up for
* read for this descriptor, which means that we never get EOF. This
* way we will get the EOF if stdin comes from /dev/null or similar.
*/
if (stdin_null_flag) {
/* Fake EOF on stdin. */
debug("Sending eof.");
@ -187,22 +201,22 @@ client_check_initial_eof_on_stdin()
packet_start(SSH_CMSG_EOF);
packet_send();
} else {
/* Enter non-blocking mode for stdin. */
enter_non_blocking();
/* Check for immediate EOF on stdin. */
len = read(fileno(stdin), buf, 1);
if (len == 0) {
/* EOF. Record that we have seen it and send EOF
to server. */
/* EOF. Record that we have seen it and send EOF to server. */
debug("Sending eof.");
stdin_eof = 1;
packet_start(SSH_CMSG_EOF);
packet_send();
} else if (len > 0) {
/* Got data. We must store the data in the
buffer, and also process it as an escape
character if appropriate. */
/*
* Got data. We must store the data in the buffer,
* and also process it as an escape character if
* appropriate.
*/
if ((unsigned char) buf[0] == escape_char)
escape_pending = 1;
else {
@ -210,13 +224,14 @@ client_check_initial_eof_on_stdin()
stdin_bytes += 1;
}
}
/* Leave non-blocking mode. */
leave_non_blocking();
}
}
/* Get packets from the connection input buffer, and process them as long
as there are packets available. */
/*
* Get packets from the connection input buffer, and process them as long as
* there are packets available.
*/
void
client_process_buffered_input_packets()
@ -255,8 +270,10 @@ client_process_buffered_input_packets()
/* Acknowledge the exit. */
packet_start(SSH_CMSG_EXIT_CONFIRMATION);
packet_send();
/* Must wait for packet to be sent since we are
exiting the loop. */
/*
* 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;
@ -300,20 +317,24 @@ client_process_buffered_input_packets()
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. */
/*
* 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 connection. */
/*
* Make packets from buffered stdin data, and buffer them for sending to the
* connection.
*/
void
client_make_packets_from_stdin_data()
@ -339,10 +360,12 @@ client_make_packets_from_stdin_data()
}
}
/* Checks if the client window has changed, and sends a packet about it to
the server if so. The actual change is detected elsewhere (by a software
interrupt on Unix); this just checks the flag and sends a message if
appropriate. */
/*
* Checks if the client window has changed, and sends a packet about it to
* the server if so. The actual change is detected elsewhere (by a software
* interrupt on Unix); this just checks the flag and sends a message if
* appropriate.
*/
void
client_check_window_change()
@ -367,8 +390,10 @@ client_check_window_change()
}
}
/* Waits until the client can do something (some data becomes available on
one of the file descriptors). */
/*
* Waits until the client can do something (some data becomes available on
* one of the file descriptors).
*/
void
client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
@ -382,8 +407,10 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
channel_not_very_much_buffered_data())
FD_SET(connection_in, readset);
/* Read from stdin, unless we have seen EOF or have very much
buffered data to send to the server. */
/*
* Read from stdin, unless we have seen EOF or have very much
* buffered data to send to the server.
*/
if (!stdin_eof && packet_not_very_much_data_to_write())
FD_SET(fileno(stdin), readset);
@ -408,13 +435,14 @@ client_wait_until_can_do_something(fd_set * readset, fd_set * writeset)
if (channel_max_fd() > max_fd)
max_fd = channel_max_fd();
/* Wait for something to happen. This will suspend the process
until some selected descriptor can be read, written, or has
some other event pending.
Note: if you want to implement SSH_MSG_IGNORE messages to fool
traffic analysis, this might be the place to do it:
just have a random timeout for the select, and send a random
SSH_MSG_IGNORE packet when the timeout expires. */
/*
* Wait for something to happen. This will suspend the process until
* some selected descriptor can be read, written, or has some other
* event pending. Note: if you want to implement SSH_MSG_IGNORE
* messages to fool traffic analysis, this might be the place to do
* it: just have a random timeout for the select, and send a random
* SSH_MSG_IGNORE packet when the timeout expires.
*/
if (select(max_fd + 1, readset, writeset, NULL, NULL) < 0) {
char buf[100];
@ -446,11 +474,12 @@ client_suspend_self()
buffer_ptr(&stderr_buffer),
buffer_len(&stderr_buffer));
/* Leave raw mode. */
leave_raw_mode();
/* Free (and clear) the buffer to reduce the amount of data that
gets written to swap. */
/*
* Free (and clear) the buffer to reduce the amount of data that gets
* written to swap.
*/
buffer_free(&stdin_buffer);
buffer_free(&stdout_buffer);
buffer_free(&stderr_buffer);
@ -474,7 +503,6 @@ client_suspend_self()
buffer_init(&stdout_buffer);
buffer_init(&stderr_buffer);
/* Re-enter raw mode. */
enter_raw_mode();
}
@ -484,8 +512,10 @@ client_process_input(fd_set * readset)
int len, pid;
char buf[8192], *s;
/* Read input from the server, and add any such data to the buffer
of the packet subsystem. */
/*
* Read input from the server, and add any such data to the buffer of
* the packet subsystem.
*/
if (FD_ISSET(connection_in, readset)) {
/* Read as much as possible. */
len = read(connection_in, buf, sizeof(buf));
@ -498,9 +528,10 @@ client_process_input(fd_set * readset)
quit_pending = 1;
return;
}
/* There is a kernel bug on Solaris that causes select to
sometimes wake up even though there is no data
available. */
/*
* There is a kernel bug on Solaris that causes select to
* sometimes wake up even though there is no data available.
*/
if (len < 0 && errno == EAGAIN)
len = 0;
@ -520,9 +551,11 @@ client_process_input(fd_set * readset)
/* Read as much as possible. */
len = read(fileno(stdin), buf, sizeof(buf));
if (len <= 0) {
/* Received EOF or error. They are treated
similarly, except that an error message is
printed if it was an error condition. */
/*
* Received EOF or error. They are treated
* similarly, except that an error message is printed
* if it was an error condition.
*/
if (len < 0) {
snprintf(buf, sizeof buf, "read: %.100s\r\n", strerror(errno));
buffer_append(&stderr_buffer, buf, strlen(buf));
@ -530,32 +563,35 @@ client_process_input(fd_set * readset)
}
/* Mark that we have seen EOF. */
stdin_eof = 1;
/* Send an EOF message to the server unless there
is data in the buffer. If there is data in the
buffer, no message will be sent now. Code
elsewhere will send the EOF when the buffer
becomes empty if stdin_eof is set. */
/*
* Send an EOF message to the server unless there is
* data in the buffer. If there is data in the
* buffer, no message will be sent now. Code
* elsewhere will send the EOF when the buffer
* becomes empty if stdin_eof is set.
*/
if (buffer_len(&stdin_buffer) == 0) {
packet_start(SSH_CMSG_EOF);
packet_send();
}
} else if (escape_char == -1) {
/* Normal successful read, and no escape
character. Just append the data to buffer. */
/*
* Normal successful read, and no escape character.
* Just append the data to buffer.
*/
buffer_append(&stdin_buffer, buf, len);
stdin_bytes += len;
} else {
/* Normal, successful read. But we have an escape
character and have to process the characters
one by one. */
/*
* Normal, successful read. But we have an escape character
* and have to process the characters one by one.
*/
unsigned int i;
for (i = 0; i < len; i++) {
unsigned char ch;
/* Get one character at a time. */
ch = buf[i];
/* Check if we have a pending escape
character. */
if (escape_pending) {
/* We have previously seen an escape character. */
/* Clear the flag now. */
@ -584,12 +620,16 @@ client_process_input(fd_set * readset)
continue;
case '&':
/* Detach the program (continue to serve connections,
but put in background and no more new connections). */
/*
* Detach the program (continue to serve connections,
* but put in background and no more new connections).
*/
if (!stdin_eof) {
/* Sending SSH_CMSG_EOF alone does not always appear
to be enough. So we try to send an EOF character
first. */
/*
* Sending SSH_CMSG_EOF alone does not always appear
* to be enough. So we try to send an EOF character
* first.
*/
packet_start(SSH_CMSG_STDIN_DATA);
packet_put_string("\004", 1);
packet_send();
@ -646,22 +686,28 @@ Supported escape sequences:\r\n\
default:
if (ch != escape_char) {
/* Escape character followed by non-special character.
Append both to the input buffer. */
/*
* Escape character followed by non-special character.
* Append both to the input buffer.
*/
buf[0] = escape_char;
buf[1] = ch;
buffer_append(&stdin_buffer, buf, 2);
stdin_bytes += 2;
continue;
}
/* Note that escape character typed twice
falls through here; the latter gets processed
as a normal character below. */
/*
* Note that escape character typed twice
* falls through here; the latter gets processed
* as a normal character below.
*/
break;
}
} else {
/* The previous character was not an escape char. Check if this
is an escape. */
/*
* The previous character was not an escape char. Check if this
* is an escape.
*/
if (last_was_cr && ch == escape_char) {
/* It is. Set the flag and continue to next character. */
escape_pending = 1;
@ -669,8 +715,10 @@ Supported escape sequences:\r\n\
}
}
/* Normal character. Record whether it was a newline, and append it to the
buffer. */
/*
* Normal character. Record whether it was a newline,
* and append it to the buffer.
*/
last_was_cr = (ch == '\r' || ch == '\n');
buf[0] = ch;
buffer_append(&stdin_buffer, buf, 1);
@ -696,8 +744,10 @@ client_process_output(fd_set * writeset)
if (errno == EAGAIN)
len = 0;
else {
/* An error or EOF was encountered. Put
an error message to stderr buffer. */
/*
* An error or EOF was encountered. Put an
* error message to stderr buffer.
*/
snprintf(buf, sizeof buf, "write stdout: %.50s\r\n", strerror(errno));
buffer_append(&stderr_buffer, buf, strlen(buf));
stderr_bytes += strlen(buf);
@ -717,8 +767,7 @@ client_process_output(fd_set * writeset)
if (errno == EAGAIN)
len = 0;
else {
/* EOF or error, but can't even print
error message. */
/* EOF or error, but can't even print error message. */
quit_pending = 1;
return;
}
@ -728,11 +777,12 @@ client_process_output(fd_set * writeset)
}
}
/* Implements the interactive session with the server. This is called
after the user has been authenticated, and a command has been
started on the remote host. If escape_char != -1, it is the character
used as an escape character for terminating or suspending the
session. */
/*
* Implements the interactive session with the server. This is called after
* the user has been authenticated, and a command has been started on the
* remote host. If escape_char != -1, it is the character used as an escape
* character for terminating or suspending the session.
*/
int
client_loop(int have_pty, int escape_char_arg)
@ -776,7 +826,6 @@ client_loop(int have_pty, int escape_char_arg)
if (have_pty)
signal(SIGWINCH, window_change_handler);
/* Enter raw mode if have a pseudo terminal. */
if (have_pty)
enter_raw_mode();
@ -787,27 +836,35 @@ client_loop(int have_pty, int escape_char_arg)
while (!quit_pending) {
fd_set readset, writeset;
/* Precess buffered packets sent by the server. */
/* Process buffered packets sent by the server. */
client_process_buffered_input_packets();
/* Make packets of buffered stdin data, and buffer them
for sending to the server. */
/*
* Make packets of buffered stdin data, and buffer them for
* sending to the server.
*/
client_make_packets_from_stdin_data();
/* Make packets from buffered channel data, and buffer
them for sending to the server. */
/*
* Make packets from buffered channel data, and buffer them
* for sending to the server.
*/
if (packet_not_very_much_data_to_write())
channel_output_poll();
/* Check if the window size has changed, and buffer a
message about it to the server if so. */
/*
* Check if the window size has changed, and buffer a message
* about it to the server if so.
*/
client_check_window_change();
if (quit_pending)
break;
/* Wait until we have something to do (something becomes
available on one of the descriptors). */
/*
* Wait until we have something to do (something becomes
* available on one of the descriptors).
*/
client_wait_until_can_do_something(&readset, &writeset);
if (quit_pending)
@ -816,16 +873,19 @@ client_loop(int have_pty, int escape_char_arg)
/* Do channel operations. */
channel_after_select(&readset, &writeset);
/* Process input from the connection and from stdin.
Buffer any data that is available. */
/*
* Process input from the connection and from stdin. Buffer
* any data that is available.
*/
client_process_input(&readset);
/* Process output to stdout and stderr. Output to the
connection is processed elsewhere (above). */
/*
* Process output to stdout and stderr. Output to the
* connection is processed elsewhere (above).
*/
client_process_output(&writeset);
/* Send as much buffered packet data as possible to the
sender. */
/* Send as much buffered packet data as possible to the sender. */
if (FD_ISSET(connection_out, &writeset))
packet_write_poll();
}
@ -839,8 +899,10 @@ client_loop(int have_pty, int escape_char_arg)
/* Stop listening for connections. */
channel_stop_listening();
/* In interactive mode (with pseudo tty) display a message
indicating that the connection has been closed. */
/*
* In interactive mode (with pseudo tty) display a message indicating
* that the connection has been closed.
*/
if (have_pty && options.log_level != SYSLOG_LEVEL_QUIET) {
snprintf(buf, sizeof buf, "Connection to %.64s closed.\r\n", host);
buffer_append(&stderr_buffer, buf, strlen(buf));
@ -868,7 +930,6 @@ client_loop(int have_pty, int escape_char_arg)
buffer_consume(&stderr_buffer, len);
}
/* Leave raw mode. */
if (have_pty)
leave_raw_mode();

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

@ -1,5 +1,34 @@
/*
* Copyright (c) 1999 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: compat.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: compat.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
#include "ssh.h"

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

@ -1,4 +1,32 @@
/* RCSID("$Id: compat.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
/*
* Copyright (c) 1999 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.
*/
/* RCSID("$Id: compat.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */
#ifndef COMPAT_H
#define COMPAT_H

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

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: compress.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: compress.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
#include "ssh.h"
#include "buffer.h"
@ -23,8 +23,10 @@ RCSID("$Id: compress.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
static z_stream incoming_stream;
static z_stream outgoing_stream;
/* Initializes compression; level is compression level from 1 to 9
(as in gzip). */
/*
* Initializes compression; level is compression level from 1 to 9
* (as in gzip).
*/
void
buffer_compress_init(int level)
@ -53,13 +55,14 @@ buffer_compress_uninit()
deflateEnd(&outgoing_stream);
}
/* Compresses the contents of input_buffer into output_buffer. All
packets compressed using this function will form a single
compressed data stream; however, data will be flushed at the end of
every call so that each output_buffer can be decompressed
independently (but in the appropriate order since they together
form a single compression stream) by the receiver. This appends
the compressed data to the output buffer. */
/*
* Compresses the contents of input_buffer into output_buffer. All packets
* compressed using this function will form a single compressed data stream;
* however, data will be flushed at the end of every call so that each
* output_buffer can be decompressed independently (but in the appropriate
* order since they together form a single compression stream) by the
* receiver. This appends the compressed data to the output buffer.
*/
void
buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
@ -106,13 +109,14 @@ buffer_compress(Buffer * input_buffer, Buffer * output_buffer)
while (outgoing_stream.avail_out == 0);
}
/* Uncompresses the contents of input_buffer into output_buffer. All
packets uncompressed using this function will form a single
compressed data stream; however, data will be flushed at the end of
every call so that each output_buffer. This must be called for the
same size units that the buffer_compress was called, and in the
same order that buffers compressed with that. This appends the
uncompressed data to the output buffer. */
/*
* Uncompresses the contents of input_buffer into output_buffer. All packets
* uncompressed using this function will form a single compressed data
* stream; however, data will be flushed at the end of every call so that
* each output_buffer. This must be called for the same size units that the
* buffer_compress was called, and in the same order that buffers compressed
* with that. This appends the uncompressed data to the output buffer.
*/
void
buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
@ -145,9 +149,11 @@ buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer)
fatal("buffer_uncompress: inflate returned Z_STREAM_ERROR");
/* NOTREACHED */
case Z_BUF_ERROR:
/* Comments in zlib.h say that we should keep
calling inflate() until we get an error. This
appears to be the error that we get. */
/*
* Comments in zlib.h say that we should keep calling
* inflate() until we get an error. This appears to
* be the error that we get.
*/
return;
case Z_MEM_ERROR:
fatal("buffer_uncompress: inflate returned Z_MEM_ERROR");

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

@ -13,34 +13,38 @@
*
*/
/* RCSID("$Id: compress.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: compress.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */
#ifndef COMPRESS_H
#define COMPRESS_H
/* Initializes compression; level is compression level from 1 to 9 (as in
gzip). */
/*
* Initializes compression; level is compression level from 1 to 9 (as in
* gzip).
*/
void buffer_compress_init(int level);
/* Frees any data structures allocated by buffer_compress_init. */
void buffer_compress_uninit();
/* Compresses the contents of input_buffer into output_buffer. All
packets compressed using this function will form a single
compressed data stream; however, data will be flushed at the end of
every call so that each output_buffer can be decompressed
independently (but in the appropriate order since they together
form a single compression stream) by the receiver. This appends
the compressed data to the output buffer. */
/*
* Compresses the contents of input_buffer into output_buffer. All packets
* compressed using this function will form a single compressed data stream;
* however, data will be flushed at the end of every call so that each
* output_buffer can be decompressed independently (but in the appropriate
* order since they together form a single compression stream) by the
* receiver. This appends the compressed data to the output buffer.
*/
void buffer_compress(Buffer * input_buffer, Buffer * output_buffer);
/* Uncompresses the contents of input_buffer into output_buffer. All
packets uncompressed using this function will form a single
compressed data stream; however, data will be flushed at the end of
every call so that each output_buffer. This must be called for the
same size units that the buffer_compress was called, and in the
same order that buffers compressed with that. This appends the
uncompressed data to the output buffer. */
/*
* Uncompresses the contents of input_buffer into output_buffer. All packets
* uncompressed using this function will form a single compressed data
* stream; however, data will be flushed at the end of every call so that
* each output_buffer. This must be called for the same size units that the
* buffer_compress was called, and in the same order that buffers compressed
* with that. This appends the uncompressed data to the output buffer.
*/
void buffer_uncompress(Buffer * input_buffer, Buffer * output_buffer);
#endif /* COMPRESS_H */

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

@ -13,13 +13,15 @@
*
*/
/* RCSID("$Id: crc32.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: crc32.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */
#ifndef CRC32_H
#define CRC32_H
/* This computes a 32 bit CRC of the data in the buffer, and returns the
CRC. The polynomial used is 0xedb88320. */
/*
* This computes a 32 bit CRC of the data in the buffer, and returns the CRC.
* The polynomial used is 0xedb88320.
*/
unsigned int crc32(const unsigned char *buf, unsigned int len);
#endif /* CRC32_H */

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

@ -1,5 +1,34 @@
/*
* Copyright (c) 1999 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: fingerprint.c,v 1.3 1999/11/24 00:26:01 deraadt Exp $");
RCSID("$Id: fingerprint.c,v 1.4 1999/11/24 16:15:25 markus Exp $");
#include "ssh.h"
#include "xmalloc.h"

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

@ -1,4 +1,32 @@
/* RCSID("$Id: fingerprint.h,v 1.2 1999/11/24 00:26:02 deraadt Exp $"); */
/*
* Copyright (c) 1999 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.
*/
/* RCSID("$Id: fingerprint.h,v 1.3 1999/11/24 16:15:25 markus Exp $"); */
#ifndef FINGERPRINT_H
#define FINGERPRINT_H

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

@ -14,16 +14,18 @@
*/
#include "includes.h"
RCSID("$Id: hostfile.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: hostfile.c,v 1.6 1999/11/25 00:54:59 damien Exp $");
#include "packet.h"
#include "ssh.h"
/* Reads a multiple-precision integer in hex from the buffer, and advances the
pointer. The integer must already be initialized. This function is
permitted to modify the buffer. This leaves *cpp to point just beyond
the last processed (and maybe modified) character. Note that this may
modify the buffer containing the number. */
/*
* Reads a multiple-precision integer in hex from the buffer, and advances
* the pointer. The integer must already be initialized. This function is
* permitted to modify the buffer. This leaves *cpp to point just beyond the
* last processed (and maybe modified) character. Note that this may modify
* the buffer containing the number.
*/
int
auth_rsa_read_bignum(char **cpp, BIGNUM * value)
@ -32,7 +34,8 @@ auth_rsa_read_bignum(char **cpp, BIGNUM * value)
int len, old;
/* Skip any leading whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++);
for (; *cp == ' ' || *cp == '\t'; cp++)
;
/* Check that it begins with a hex digit. */
if (*cp < '0' || *cp > '9')
@ -42,7 +45,8 @@ auth_rsa_read_bignum(char **cpp, BIGNUM * value)
*cpp = cp;
/* Move forward until all hex digits skipped. */
for (; *cp >= '0' && *cp <= '9'; cp++);
for (; *cp >= '0' && *cp <= '9'; cp++)
;
/* Compute the length of the hex number. */
len = cp - *cpp;
@ -51,7 +55,6 @@ auth_rsa_read_bignum(char **cpp, BIGNUM * value)
old = *cp;
*cp = 0;
/* Parse the number. */
if (BN_dec2bn(&value, *cpp) == 0)
return 0;
@ -64,8 +67,10 @@ auth_rsa_read_bignum(char **cpp, BIGNUM * value)
return 1;
}
/* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
over the key. Skips any whitespace at the beginning and at end. */
/*
* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
* over the key. Skips any whitespace at the beginning and at end.
*/
int
auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
@ -74,7 +79,8 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
char *cp;
/* Skip leading whitespace. */
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++);
for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
;
/* Get number of bits. */
if (*cp < '0' || *cp > '9')
@ -91,7 +97,8 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
return 0;
/* Skip trailing whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++);
for (; *cp == ' ' || *cp == '\t'; cp++)
;
/* Return results. */
*cpp = cp;
@ -99,10 +106,12 @@ auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n)
return 1;
}
/* Tries to match the host name (which must be in all lowercase) against the
comma-separated sequence of subpatterns (each possibly preceded by ! to
indicate negation). Returns true if there is a positive match; zero
otherwise. */
/*
* Tries to match the host name (which must be in all lowercase) against the
* comma-separated sequence of subpatterns (each possibly preceded by ! to
* indicate negation). Returns true if there is a positive match; zero
* otherwise.
*/
int
match_hostname(const char *host, const char *pattern, unsigned int len)
@ -121,18 +130,19 @@ match_hostname(const char *host, const char *pattern, unsigned int len)
} else
negated = 0;
/* Extract the subpattern up to a comma or end. Convert
the subpattern to lowercase. */
/*
* Extract the subpattern up to a comma or end. Convert the
* subpattern to lowercase.
*/
for (subi = 0;
i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
i < len && subi < sizeof(sub) - 1 && pattern[i] != ',';
subi++, i++)
sub[subi] = isupper(pattern[i]) ? tolower(pattern[i]) : pattern[i];
/* If subpattern too long, return failure (no match). */
if (subi >= sizeof(sub) - 1)
return 0;
/* If the subpattern was terminated by a comma, skip the
comma. */
/* If the subpattern was terminated by a comma, skip the comma. */
if (i < len && pattern[i] == ',')
i++;
@ -142,24 +152,25 @@ match_hostname(const char *host, const char *pattern, unsigned int len)
/* Try to match the subpattern against the host name. */
if (match_pattern(host, sub)) {
if (negated)
return 0; /* Fail if host matches
any negated subpattern. */
return 0; /* Fail */
else
got_positive = 1;
}
}
/* Return success if got a positive match. If there was a
negative match, we have already returned zero and never get
here. */
/*
* Return success if got a positive match. If there was a negative
* match, we have already returned zero and never get here.
*/
return got_positive;
}
/* Checks whether the given host (which must be in all lowercase) is
already in the list of our known hosts.
Returns HOST_OK if the host is known and has the specified key,
HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
but used to have a different host key. */
/*
* Checks whether the given host (which must be in all lowercase) is already
* in the list of our known hosts. Returns HOST_OK if the host is known and
* has the specified key, HOST_NEW if the host is not known, and HOST_CHANGED
* if the host is known but used to have a different host key.
*/
HostStatus
check_host_in_hostfile(const char *filename, const char *host,
@ -180,9 +191,11 @@ check_host_in_hostfile(const char *filename, const char *host,
/* Cache the length of the host name. */
hostlen = strlen(host);
/* Return value when the loop terminates. This is set to
HOST_CHANGED if we have seen a different key for the host and
have not found the proper one. */
/*
* Return value when the loop terminates. This is set to
* HOST_CHANGED if we have seen a different key for the host and have
* not found the proper one.
*/
end_return = HOST_NEW;
/* size of modulus 'n' */
@ -193,15 +206,15 @@ check_host_in_hostfile(const char *filename, const char *host,
cp = line;
linenum++;
/* Skip any leading whitespace. */
for (; *cp == ' ' || *cp == '\t'; cp++);
/* Ignore comment lines and empty lines. */
/* Skip any leading whitespace, comments and empty lines. */
for (; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '#' || *cp == '\n')
continue;
/* Find the end of the host name portion. */
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++);
for (cp2 = cp; *cp2 && *cp2 != ' ' && *cp2 != '\t'; cp2++)
;
/* Check if the host name matches. */
if (!match_hostname(host, cp, (unsigned int) (cp2 - cp)))
@ -210,8 +223,10 @@ check_host_in_hostfile(const char *filename, const char *host,
/* Got a match. Skip host name. */
cp = cp2;
/* Extract the key from the line. This will skip any
leading whitespace. Ignore badly formatted lines. */
/*
* Extract the key from the line. This will skip any leading
* whitespace. Ignore badly formatted lines.
*/
if (!auth_rsa_read_key(&cp, &kbits, ke, kn))
continue;
@ -228,21 +243,27 @@ check_host_in_hostfile(const char *filename, const char *host,
fclose(f);
return HOST_OK;
}
/* They do not match. We will continue to go through the
file; however, we note that we will not return that it
is new. */
/*
* They do not match. We will continue to go through the
* file; however, we note that we will not return that it is
* new.
*/
end_return = HOST_CHANGED;
}
/* Clear variables and close the file. */
fclose(f);
/* Return either HOST_NEW or HOST_CHANGED, depending on whether we
saw a different key for the host. */
/*
* Return either HOST_NEW or HOST_CHANGED, depending on whether we
* saw a different key for the host.
*/
return end_return;
}
/* Appends an entry to the host file. Returns false if the entry
could not be appended. */
/*
* Appends an entry to the host file. Returns false if the entry could not
* be appended.
*/
int
add_host_to_hostfile(const char *filename, const char *host,

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

@ -87,8 +87,10 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
#define _PATH_RSH "/usr/bin/rsh"
#endif /* _PATH_RSH */
/* Define this to use pipes instead of socketpairs for communicating with the
client program. Socketpairs do not seem to work on all systems. */
/*
* Define this to use pipes instead of socketpairs for communicating with the
* client program. Socketpairs do not seem to work on all systems.
*/
#define USE_PIPES 1
#endif /* INCLUDES_H */

6
log.c
Просмотреть файл

@ -1,11 +1,9 @@
/*
*
* Shared versions of debug(), log(), etc.
*
*/
*/
#include "includes.h"
RCSID("$OpenBSD: log.c,v 1.5 1999/11/24 00:26:02 deraadt Exp $");
RCSID("$OpenBSD: log.c,v 1.6 1999/11/24 19:53:47 markus Exp $");
#include "ssh.h"
#include "xmalloc.h"

29
login.c
Просмотреть файл

@ -18,7 +18,7 @@
*/
#include "includes.h"
RCSID("$Id: login.c,v 1.3 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: login.c,v 1.4 1999/11/25 00:54:59 damien Exp $");
#include <utmp.h>
#include "ssh.h"
@ -30,12 +30,16 @@ RCSID("$Id: login.c,v 1.3 1999/11/24 13:26:22 damien Exp $");
# include <lastlog.h>
#endif
/* Returns the time when the user last logged in. Returns 0 if the
information is not available. This must be called before record_login.
The host the user logged in from will be returned in buf. */
/*
* Returns the time when the user last logged in. Returns 0 if the
* information is not available. This must be called before record_login.
* The host the user logged in from will be returned in buf.
*/
/* Returns the time when the user last logged in (or 0 if no previous login
is found). The name of the host used last time is returned in buf. */
/*
* Returns the time when the user last logged in (or 0 if no previous login
* is found). The name of the host used last time is returned in buf.
*/
unsigned long
get_last_login_time(uid_t uid, const char *logname,
@ -64,8 +68,10 @@ get_last_login_time(uid_t uid, const char *logname,
return ll.ll_time;
}
/* Records that the user has logged in. I these parts of operating systems
were more standardized. */
/*
* Records that the user has logged in. I these parts of operating systems
* were more standardized.
*/
void
record_login(int pid, const char *ttyname, const char *user, uid_t uid,
@ -95,9 +101,10 @@ record_login(int pid, const char *ttyname, const char *user, uid_t uid,
/* Update lastlog unless actually recording a logout. */
if (strcmp(user, "") != 0) {
/* It is safer to bzero the lastlog structure first
because some systems might have some extra fields in it
(e.g. SGI) */
/*
* It is safer to bzero the lastlog structure first because
* some systems might have some extra fields in it (e.g. SGI)
*/
memset(&ll, 0, sizeof(ll));
/* Update lastlog. */

35
match.c
Просмотреть файл

@ -14,12 +14,14 @@
*/
#include "includes.h"
RCSID("$Id: match.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: match.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
#include "ssh.h"
/* Returns true if the given string matches the pattern (which may contain
? and * as wildcards), and zero if it does not match. */
/*
* 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)
@ -29,7 +31,6 @@ match_pattern(const char *s, const char *pattern)
if (!*pattern)
return !*s;
/* Process '*'. */
if (*pattern == '*') {
/* Skip the asterisk. */
pattern++;
@ -40,9 +41,11 @@ match_pattern(const char *s, const char *pattern)
/* If next character in pattern is known, optimize. */
if (*pattern != '?' && *pattern != '*') {
/* Look instances of the next character in
pattern, and try to match starting from
those. */
/*
* Look instances of the next character in
* pattern, and try to match starting from
* those.
*/
for (; *s; s++)
if (*s == *pattern &&
match_pattern(s + 1, pattern + 1))
@ -50,26 +53,28 @@ match_pattern(const char *s, const char *pattern)
/* Failed. */
return 0;
}
/* Move ahead one character at a time and try to
match at each position. */
/*
* Move ahead one character at a time and try to
* match at each position.
*/
for (; *s; s++)
if (match_pattern(s, pattern))
return 1;
/* Failed. */
return 0;
}
/* There must be at least one more character in the
string. If we are at the end, fail. */
/*
* There must be at least one more character in the string.
* If we are at the end, fail.
*/
if (!*s)
return 0;
/* Check if the next character of the string is
acceptable. */
/* Check if the next character of the string is acceptable. */
if (*pattern != '?' && *pattern != *s)
return 0;
/* Move to the next character, both in string and in
pattern. */
/* Move to the next character, both in string and in pattern. */
s++;
pattern++;
}

10
mpaux.h
Просмотреть файл

@ -13,14 +13,16 @@
* precision integers.
*/
/* RCSID("$Id: mpaux.h,v 1.3 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: mpaux.h,v 1.4 1999/11/25 00:54:59 damien Exp $"); */
#ifndef MPAUX_H
#define MPAUX_H
/* Computes a 16-byte session id in the global variable session_id.
The session id is computed by concatenating the linearized, msb
first representations of host_key_n, session_key_n, and the cookie. */
/*
* Computes a 16-byte session id in the global variable session_id. The
* session id is computed by concatenating the linearized, msb first
* representations of host_key_n, session_key_n, and the cookie.
*/
void
compute_session_id(unsigned char session_id[16],
unsigned char cookie[8],

34
nchan.c
Просмотреть файл

@ -1,5 +1,34 @@
/*
* Copyright (c) 1999 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: nchan.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: nchan.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
#include "ssh.h"
@ -173,9 +202,10 @@ chan_send_oclose(Channel *c)
static void
chan_shutdown_write(Channel *c)
{
/* shutdown failure is allowed if write failed already */
debug("channel %d: shutdown_write", c->self);
if (shutdown(c->sock, SHUT_WR) < 0)
error("chan_shutdown_write failed for #%d/fd%d: %.100s",
debug("chan_shutdown_write failed for #%d/fd%d: %.100s",
c->self, c->sock, strerror(errno));
}
static void

31
nchan.h
Просмотреть файл

@ -1,4 +1,33 @@
/* RCSID("$Id: nchan.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
/*
* Copyright (c) 1999 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.
*/
/* RCSID("$Id: nchan.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */
#ifndef NCHAN_H
#define NCHAN_H

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

@ -1,3 +1,31 @@
.\"
.\" Copyright (c) 1999 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.
.\"
.TL
OpenSSH Channel Close Protocol 1.5 Implementation
.SH

181
packet.c
Просмотреть файл

@ -15,7 +15,7 @@
*/
#include "includes.h"
RCSID("$Id: packet.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: packet.c,v 1.6 1999/11/25 00:54:59 damien Exp $");
#include "xmalloc.h"
#include "buffer.h"
@ -29,15 +29,19 @@ RCSID("$Id: packet.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
#include "compress.h"
#include "deattack.h"
/* This variable contains the file descriptors used for communicating with
the other side. connection_in is used for reading; connection_out
for writing. These can be the same descriptor, in which case it is
assumed to be a socket. */
/*
* This variable contains the file descriptors used for communicating with
* the other side. connection_in is used for reading; connection_out for
* writing. These can be the same descriptor, in which case it is assumed to
* be a socket.
*/
static int connection_in = -1;
static int connection_out = -1;
/* Cipher type. This value is only used to determine whether to pad the
packets with zeroes or random data. */
/*
* Cipher type. This value is only used to determine whether to pad the
* packets with zeroes or random data.
*/
static int cipher_type = SSH_CIPHER_NONE;
/* Protocol flags for the remote side. */
@ -76,8 +80,10 @@ static int initialized = 0;
/* Set to true if the connection is interactive. */
static int interactive_mode = 0;
/* Sets the descriptors used for communication. Disables encryption until
packet_set_encryption_key is called. */
/*
* Sets the descriptors used for communication. Disables encryption until
* packet_set_encryption_key is called.
*/
void
packet_set_connection(int fd_in, int fd_out)
@ -171,8 +177,10 @@ packet_get_protocol_flags()
return remote_protocol_flags;
}
/* Starts packet compression from the next packet on in both directions.
Level is compression level 1 (fastest) - 9 (slow, best) as in gzip. */
/*
* Starts packet compression from the next packet on in both directions.
* Level is compression level 1 (fastest) - 9 (slow, best) as in gzip.
*/
void
packet_start_compression(int level)
@ -184,8 +192,10 @@ packet_start_compression(int level)
buffer_compress_init(level);
}
/* Encrypts the given number of bytes, copying from src to dest.
bytes is known to be a multiple of 8. */
/*
* Encrypts the given number of bytes, copying from src to dest. bytes is
* known to be a multiple of 8.
*/
void
packet_encrypt(CipherContext * cc, void *dest, void *src,
@ -194,8 +204,10 @@ packet_encrypt(CipherContext * cc, void *dest, void *src,
cipher_encrypt(cc, dest, src, bytes);
}
/* Decrypts the given number of bytes, copying from src to dest.
bytes is known to be a multiple of 8. */
/*
* Decrypts the given number of bytes, copying from src to dest. bytes is
* known to be a multiple of 8.
*/
void
packet_decrypt(CipherContext * cc, void *dest, void *src,
@ -206,8 +218,10 @@ packet_decrypt(CipherContext * cc, void *dest, void *src,
if ((bytes % 8) != 0)
fatal("packet_decrypt: bad ciphertext length %d", bytes);
/* Cryptographic attack detector for ssh - Modifications for packet.c
(C)1998 CORE-SDI, Buenos Aires Argentina Ariel Futoransky(futo@core-sdi.com) */
/*
* Cryptographic attack detector for ssh - Modifications for packet.c
* (C)1998 CORE-SDI, Buenos Aires Argentina Ariel Futoransky(futo@core-sdi.com)
*/
switch (cc->type) {
case SSH_CIPHER_NONE:
@ -224,9 +238,11 @@ packet_decrypt(CipherContext * cc, void *dest, void *src,
cipher_decrypt(cc, dest, src, bytes);
}
/* Causes any further packets to be encrypted using the given key. The same
key is used for both sending and reception. However, both directions
are encrypted independently of each other. */
/*
* Causes any further packets to be encrypted using the given key. The same
* key is used for both sending and reception. However, both directions are
* encrypted independently of each other.
*/
void
packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
@ -283,8 +299,10 @@ packet_put_bignum(BIGNUM * value)
buffer_put_bignum(&outgoing_packet, value);
}
/* Finalizes and sends the packet. If the encryption key has been set,
encrypts the packet before sending. */
/*
* Finalizes and sends the packet. If the encryption key has been set,
* encrypts the packet before sending.
*/
void
packet_send()
@ -294,8 +312,10 @@ packet_send()
unsigned int checksum;
u_int32_t rand = 0;
/* If using packet compression, compress the payload of the
outgoing packet. */
/*
* If using packet compression, compress the payload of the outgoing
* packet.
*/
if (packet_compression) {
buffer_clear(&compression_buffer);
/* Skip padding. */
@ -348,14 +368,18 @@ packet_send()
buffer_clear(&outgoing_packet);
/* Note that the packet is now only buffered in output. It won\'t
be actually sent until packet_write_wait or packet_write_poll
is called. */
/*
* Note that the packet is now only buffered in output. It won\'t be
* actually sent until packet_write_wait or packet_write_poll is
* called.
*/
}
/* Waits until a packet has been received, and returns its type. Note that
no other data is processed until this returns, so this function should
not be used during the interactive session. */
/*
* Waits until a packet has been received, and returns its type. Note that
* no other data is processed until this returns, so this function should not
* be used during the interactive session.
*/
int
packet_read(int *payload_len_ptr)
@ -379,12 +403,16 @@ packet_read(int *payload_len_ptr)
/* If we got a packet, return it. */
if (type != SSH_MSG_NONE)
return type;
/* Otherwise, wait for some data to arrive, add it to the
buffer, and try again. */
/*
* Otherwise, wait for some data to arrive, add it to the
* buffer, and try again.
*/
FD_ZERO(&set);
FD_SET(connection_in, &set);
/* Wait for some data to arrive. */
select(connection_in + 1, &set, NULL, NULL, NULL);
/* Read data from the socket. */
len = read(connection_in, buf, sizeof(buf));
if (len == 0)
@ -397,8 +425,10 @@ packet_read(int *payload_len_ptr)
/* NOTREACHED */
}
/* Waits until a packet has been received, verifies that its type matches
that given, and gives a fatal error and exits if there is a mismatch. */
/*
* Waits until a packet has been received, verifies that its type matches
* that given, and gives a fatal error and exits if there is a mismatch.
*/
void
packet_read_expect(int *payload_len_ptr, int expected_type)
@ -516,8 +546,10 @@ restart:
return (unsigned char) buf[0];
}
/* Buffers the given amount of input characters. This is intended to be
used together with packet_read_poll. */
/*
* Buffers the given amount of input characters. This is intended to be used
* together with packet_read_poll.
*/
void
packet_process_incoming(const char *buf, unsigned int len)
@ -543,8 +575,10 @@ packet_get_int()
return buffer_get_int(&incoming_packet);
}
/* Returns an arbitrary precision integer from the packet data. The integer
must have been initialized before this call. */
/*
* Returns an arbitrary precision integer from the packet data. The integer
* must have been initialized before this call.
*/
void
packet_get_bignum(BIGNUM * value, int *length_ptr)
@ -552,25 +586,27 @@ packet_get_bignum(BIGNUM * value, int *length_ptr)
*length_ptr = buffer_get_bignum(&incoming_packet, value);
}
/* Returns a string from the packet data. The string is allocated using
xmalloc; it is the responsibility of the calling program to free it when
no longer needed. The length_ptr argument may be NULL, or point to an
integer into which the length of the string is stored. */
/*
* Returns a string from the packet data. The string is allocated using
* xmalloc; it is the responsibility of the calling program to free it when
* no longer needed. The length_ptr argument may be NULL, or point to an
* integer into which the length of the string is stored.
*/
char
*
char *
packet_get_string(unsigned int *length_ptr)
{
return buffer_get_string(&incoming_packet, length_ptr);
}
/* Sends a diagnostic message from the server to the client. This message
can be sent at any time (but not while constructing another message).
The message is printed immediately, but only if the client is being
executed in verbose mode. These messages are primarily intended to
ease debugging authentication problems. The length of the formatted
message must not exceed 1024 bytes. This will automatically call
packet_write_wait. */
/*
* Sends a diagnostic message from the server to the client. This message
* can be sent at any time (but not while constructing another message). The
* message is printed immediately, but only if the client is being executed
* in verbose mode. These messages are primarily intended to ease debugging
* authentication problems. The length of the formatted message must not
* exceed 1024 bytes. This will automatically call packet_write_wait.
*/
void
packet_send_debug(const char *fmt,...)
@ -588,10 +624,12 @@ packet_send_debug(const char *fmt,...)
packet_write_wait();
}
/* Logs the error plus constructs and sends a disconnect
packet, closes the connection, and exits. This function never returns.
The error message should not contain a newline. The length of the
formatted message must not exceed 1024 bytes. */
/*
* Logs the error plus constructs and sends a disconnect packet, closes the
* connection, and exits. This function never returns. The error message
* should not contain a newline. The length of the formatted message must
* not exceed 1024 bytes.
*/
void
packet_disconnect(const char *fmt,...)
@ -603,8 +641,10 @@ packet_disconnect(const char *fmt,...)
fatal("packet_disconnect called recursively.");
disconnecting = 1;
/* Format the message. Note that the caller must make sure the
message is of limited size. */
/*
* Format the message. Note that the caller must make sure the
* message is of limited size.
*/
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
@ -625,8 +665,7 @@ packet_disconnect(const char *fmt,...)
fatal("Disconnecting: %.100s", buf);
}
/* Checks if there is any buffered output, and tries to write some of the
output. */
/* Checks if there is any buffered output, and tries to write some of the output. */
void
packet_write_poll()
@ -644,8 +683,10 @@ packet_write_poll()
}
}
/* Calls packet_write_poll repeatedly until all pending output data has
been written. */
/*
* Calls packet_write_poll repeatedly until all pending output data has been
* written.
*/
void
packet_write_wait()
@ -689,8 +730,10 @@ packet_set_interactive(int interactive, int keepalives)
/* Record that we are in interactive mode. */
interactive_mode = interactive;
/* Only set socket options if using a socket (as indicated by the
descriptors being the same). */
/*
* Only set socket options if using a socket (as indicated by the
* descriptors being the same).
*/
if (connection_in != connection_out)
return;
@ -701,8 +744,10 @@ packet_set_interactive(int interactive, int keepalives)
error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
}
if (interactive) {
/* Set IP options for an interactive connection. Use
IPTOS_LOWDELAY and TCP_NODELAY. */
/*
* Set IP options for an interactive connection. Use
* IPTOS_LOWDELAY and TCP_NODELAY.
*/
int lowdelay = IPTOS_LOWDELAY;
if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &lowdelay,
sizeof(lowdelay)) < 0)
@ -711,8 +756,10 @@ packet_set_interactive(int interactive, int keepalives)
sizeof(on)) < 0)
error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
} else {
/* Set IP options for a non-interactive connection. Use
IPTOS_THROUGHPUT. */
/*
* Set IP options for a non-interactive connection. Use
* IPTOS_THROUGHPUT.
*/
int throughput = IPTOS_THROUGHPUT;
if (setsockopt(connection_in, IPPROTO_IP, IP_TOS, (void *) &throughput,
sizeof(throughput)) < 0)

118
packet.h
Просмотреть файл

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: packet.h,v 1.6 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: packet.h,v 1.7 1999/11/25 00:54:59 damien Exp $"); */
#ifndef PACKET_H
#define PACKET_H
@ -27,10 +27,11 @@
#include <ssl/bn.h>
#endif
/* Sets the socket used for communication. Disables encryption until
packet_set_encryption_key is called. It is permissible that fd_in
and fd_out are the same descriptor; in that case it is assumed to
be a socket. */
/*
* Sets the socket used for communication. Disables encryption until
* packet_set_encryption_key is called. It is permissible that fd_in and
* fd_out are the same descriptor; in that case it is assumed to be a socket.
*/
void packet_set_connection(int fd_in, int fd_out);
/* Puts the connection file descriptors into non-blocking mode. */
@ -42,20 +43,25 @@ int packet_get_connection_in(void);
/* Returns the file descriptor used for output. */
int packet_get_connection_out(void);
/* Closes the connection (both descriptors) and clears and frees
internal data structures. */
/*
* Closes the connection (both descriptors) and clears and frees internal
* data structures.
*/
void packet_close(void);
/* Causes any further packets to be encrypted using the given key. The same
key is used for both sending and reception. However, both directions
are encrypted independently of each other. Cipher types are
defined in ssh.h. */
/*
* Causes any further packets to be encrypted using the given key. The same
* key is used for both sending and reception. However, both directions are
* encrypted independently of each other. Cipher types are defined in ssh.h.
*/
void
packet_set_encryption_key(const unsigned char *key, unsigned int keylen,
int cipher_type);
/* Sets remote side protocol flags for the current connection. This can
be called at any time. */
/*
* Sets remote side protocol flags for the current connection. This can be
* called at any time.
*/
void packet_set_protocol_flags(unsigned int flags);
/* Returns the remote protocol flags set earlier by the above function. */
@ -64,8 +70,10 @@ unsigned int packet_get_protocol_flags(void);
/* Enables compression in both directions starting from the next packet. */
void packet_start_compression(int level);
/* Informs that the current session is interactive. Sets IP flags for optimal
performance in interactive use. */
/*
* Informs that the current session is interactive. Sets IP flags for
* optimal performance in interactive use.
*/
void packet_set_interactive(int interactive, int keepalives);
/* Returns true if the current connection is interactive. */
@ -86,28 +94,35 @@ void packet_put_bignum(BIGNUM * value);
/* Appends a string to packet data. */
void packet_put_string(const char *buf, unsigned int len);
/* Finalizes and sends the packet. If the encryption key has been set,
encrypts the packet before sending. */
/*
* Finalizes and sends the packet. If the encryption key has been set,
* encrypts the packet before sending.
*/
void packet_send(void);
/* Waits until a packet has been received, and returns its type. */
int packet_read(int *payload_len_ptr);
/* Waits until a packet has been received, verifies that its type matches
that given, and gives a fatal error and exits if there is a mismatch. */
/*
* Waits until a packet has been received, verifies that its type matches
* that given, and gives a fatal error and exits if there is a mismatch.
*/
void packet_read_expect(int *payload_len_ptr, int type);
/* Checks if a full packet is available in the data received so far via
packet_process_incoming. If so, reads the packet; otherwise returns
SSH_MSG_NONE. This does not wait for data from the connection.
SSH_MSG_DISCONNECT is handled specially here. Also,
SSH_MSG_IGNORE messages are skipped by this function and are never returned
to higher levels. */
/*
* Checks if a full packet is available in the data received so far via
* packet_process_incoming. If so, reads the packet; otherwise returns
* SSH_MSG_NONE. This does not wait for data from the connection.
* SSH_MSG_DISCONNECT is handled specially here. Also, SSH_MSG_IGNORE
* messages are skipped by this function and are never returned to higher
* levels.
*/
int packet_read_poll(int *packet_len_ptr);
/* Buffers the given amount of input characters. This is intended to be
used together with packet_read_poll. */
/*
* Buffers the given amount of input characters. This is intended to be used
* together with packet_read_poll.
*/
void packet_process_incoming(const char *buf, unsigned int len);
/* Returns a character (0-255) from the packet data. */
@ -116,34 +131,41 @@ unsigned int packet_get_char(void);
/* Returns an integer from the packet data. */
unsigned int packet_get_int(void);
/* Returns an arbitrary precision integer from the packet data. The integer
must have been initialized before this call. */
/*
* Returns an arbitrary precision integer from the packet data. The integer
* must have been initialized before this call.
*/
void packet_get_bignum(BIGNUM * value, int *length_ptr);
/* Returns a string from the packet data. The string is allocated using
xmalloc; it is the responsibility of the calling program to free it when
no longer needed. The length_ptr argument may be NULL, or point to an
integer into which the length of the string is stored. */
/*
* Returns a string from the packet data. The string is allocated using
* xmalloc; it is the responsibility of the calling program to free it when
* no longer needed. The length_ptr argument may be NULL, or point to an
* integer into which the length of the string is stored.
*/
char *packet_get_string(unsigned int *length_ptr);
/* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
packet, closes the connection, and exits. This function never returns.
The error message should not contain a newline. The total length of the
message must not exceed 1024 bytes. */
/*
* Logs the error in syslog using LOG_INFO, constructs and sends a disconnect
* packet, closes the connection, and exits. This function never returns.
* The error message should not contain a newline. The total length of the
* message must not exceed 1024 bytes.
*/
void packet_disconnect(const char *fmt,...);
/* Sends a diagnostic message to the other side. This message
can be sent at any time (but not while constructing another message).
The message is printed immediately, but only if the client is being
executed in verbose mode. These messages are primarily intended to
ease debugging authentication problems. The total length of the message
must not exceed 1024 bytes. This will automatically call
packet_write_wait. If the remote side protocol flags do not indicate
that it supports SSH_MSG_DEBUG, this will do nothing. */
/*
* Sends a diagnostic message to the other side. This message can be sent at
* any time (but not while constructing another message). The message is
* printed immediately, but only if the client is being executed in verbose
* mode. These messages are primarily intended to ease debugging
* authentication problems. The total length of the message must not exceed
* 1024 bytes. This will automatically call packet_write_wait. If the
* remote side protocol flags do not indicate that it supports SSH_MSG_DEBUG,
* this will do nothing.
*/
void packet_send_debug(const char *fmt,...);
/* Checks if there is any buffered output, and tries to write some of the
output. */
/* Checks if there is any buffered output, and tries to write some of the output. */
void packet_write_poll(void);
/* Waits until all pending output data has been written. */

44
pty.c
Просмотреть файл

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: pty.c,v 1.4 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: pty.c,v 1.5 1999/11/25 00:54:59 damien Exp $");
#include "pty.h"
#include "ssh.h"
@ -32,10 +32,12 @@ RCSID("$Id: pty.c,v 1.4 1999/11/24 13:26:22 damien Exp $");
#define O_NOCTTY 0
#endif
/* Allocates and opens a pty. Returns 0 if no pty could be allocated,
or nonzero if a pty was successfully allocated. On success, open file
descriptors for the pty and tty sides and the name of the tty side are
returned (the buffer must be able to hold at least 64 characters). */
/*
* Allocates and opens a pty. Returns 0 if no pty could be allocated, or
* nonzero if a pty was successfully allocated. On success, open file
* descriptors for the pty and tty sides and the name of the tty side are
* returned (the buffer must be able to hold at least 64 characters).
*/
int
pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
@ -52,8 +54,10 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
return 1;
#else /* HAVE_OPENPTY */
#ifdef HAVE__GETPTY
/* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates
more pty's automagically when needed */
/*
* _getpty(3) exists in SGI Irix 4.x, 5.x & 6.x -- it generates more
* pty's automagically when needed
*/
char *slave;
slave = _getpty(ptyfd, O_RDWR, 0622, 0);
@ -72,8 +76,10 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
return 1;
#else /* HAVE__GETPTY */
#ifdef HAVE_DEV_PTMX
/* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3
also has bsd-style ptys, but they simply do not work.) */
/*
* This code is used e.g. on Solaris 2.x. (Note that Solaris 2.3
* also has bsd-style ptys, but they simply do not work.)
*/
int ptm;
char *pts;
@ -103,8 +109,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
close(*ptyfd);
return 0;
}
/* Push the appropriate streams modules, as described in Solaris
pts(7). */
/* Push the appropriate streams modules, as described in Solaris pts(7). */
if (ioctl(*ttyfd, I_PUSH, "ptem") < 0)
error("ioctl I_PUSH ptem: %.100s", strerror(errno));
if (ioctl(*ttyfd, I_PUSH, "ldterm") < 0)
@ -138,8 +143,7 @@ pty_allocate(int *ptyfd, int *ttyfd, char *namebuf)
/* BSD-style pty code. */
char buf[64];
int i;
const char *ptymajors =
"pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *ptymajors = "pqrstuvwxyzabcdefghijklmnoABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *ptyminors = "0123456789abcdef";
int num_minors = strlen(ptyminors);
int num_ptys = strlen(ptymajors) * num_minors;
@ -198,8 +202,10 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname)
if (setsid() < 0)
error("setsid: %.100s", strerror(errno));
/* Verify that we are successfully disconnected from the
controlling tty. */
/*
* Verify that we are successfully disconnected from the controlling
* tty.
*/
fd = open("/dev/tty", O_RDWR | O_NOCTTY);
if (fd >= 0) {
error("Failed to disconnect from controlling tty.");
@ -208,9 +214,11 @@ pty_make_controlling_tty(int *ttyfd, const char *ttyname)
/* Make it our controlling tty. */
#ifdef TIOCSCTTY
debug("Setting controlling tty using TIOCSCTTY.");
/* We ignore errors from this, because HPSUX defines TIOCSCTTY,
but returns EINVAL with these arguments, and there is
absolutely no documentation. */
/*
* We ignore errors from this, because HPSUX defines TIOCSCTTY, but
* returns EINVAL with these arguments, and there is absolutely no
* documentation.
*/
ioctl(*ttyfd, TIOCSCTTY, NULL);
#endif /* TIOCSCTTY */
fd = open(ttyname, O_RDWR);

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

@ -13,23 +13,29 @@
* tty.
*/
/* RCSID("$Id: pty.h,v 1.2 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: pty.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */
#ifndef PTY_H
#define PTY_H
/* Allocates and opens a pty. Returns 0 if no pty could be allocated,
or nonzero if a pty was successfully allocated. On success, open file
descriptors for the pty and tty sides and the name of the tty side are
returned (the buffer must be able to hold at least 64 characters). */
/*
* Allocates and opens a pty. Returns 0 if no pty could be allocated, or
* nonzero if a pty was successfully allocated. On success, open file
* descriptors for the pty and tty sides and the name of the tty side are
* returned (the buffer must be able to hold at least 64 characters).
*/
int pty_allocate(int *ptyfd, int *ttyfd, char *ttyname);
/* Releases the tty. Its ownership is returned to root, and permissions to
0666. */
/*
* Releases the tty. Its ownership is returned to root, and permissions to
* 0666.
*/
void pty_release(const char *ttyname);
/* Makes the tty the processes controlling tty and sets it to sane modes.
This may need to reopen the tty to get rid of possible eavesdroppers. */
/*
* Makes the tty the processes controlling tty and sets it to sane modes.
* This may need to reopen the tty to get rid of possible eavesdroppers.
*/
void pty_make_controlling_tty(int *ttyfd, const char *ttyname);
/* Changes the window size associated with the pty. */

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

@ -74,9 +74,11 @@ uudecode(const char *bufcoded, unsigned char *bufplain, int outbufsize)
while (*bufcoded == ' ' || *bufcoded == '\t')
bufcoded++;
/* Figure out how many characters are in the input buffer. If this
would decode into more bytes than would fit into the output
buffer, adjust the number of input bytes downwards. */
/*
* Figure out how many characters are in the input buffer. If this
* would decode into more bytes than would fit into the output
* buffer, adjust the number of input bytes downwards.
*/
bufin = bufcoded;
while (DEC(*(bufin++)) <= MAXVAL);
nprbytes = bufin - bufcoded - 1;

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

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: readconf.c,v 1.5 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: readconf.c,v 1.6 1999/11/25 00:54:59 damien Exp $");
#include "ssh.h"
#include "cipher.h"
@ -158,8 +158,10 @@ static struct {
#define WHITESPACE " \t\r\n"
/* Adds a local TCP/IP port forward to options. Never returns if there
is an error. */
/*
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
*/
void
add_local_forward(Options *options, int port, const char *host,
@ -179,8 +181,10 @@ add_local_forward(Options *options, int port, const char *host,
fwd->host_port = host_port;
}
/* Adds a remote TCP/IP port forward to options. Never returns if there
is an error. */
/*
* Adds a remote TCP/IP port forward to options. Never returns if there is
* an error.
*/
void
add_remote_forward(Options *options, int port, const char *host,
@ -196,8 +200,10 @@ add_remote_forward(Options *options, int port, const char *host,
fwd->host_port = host_port;
}
/* Returns the number of the token pointed to by cp of length len.
Never returns if the token is not known. */
/*
* Returns the number of the token pointed to by cp of length len. Never
* returns if the token is not known.
*/
static OpCodes
parse_token(const char *cp, const char *filename, int linenum)
@ -205,7 +211,7 @@ parse_token(const char *cp, const char *filename, int linenum)
unsigned int i;
for (i = 0; keywords[i].name; i++)
if (strcmp(cp, keywords[i].name) == 0)
if (strcasecmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
@ -213,15 +219,17 @@ parse_token(const char *cp, const char *filename, int linenum)
return oBadOption;
}
/* Processes a single option line as used in the configuration files.
This only sets those values that have not already been set. */
/*
* Processes a single option line as used in the configuration files. This
* only sets those values that have not already been set.
*/
int
process_config_line(Options *options, const char *host,
char *line, const char *filename, int linenum,
int *activep)
{
char buf[256], *cp, *string, **charptr;
char buf[256], *cp, *string, **charptr, *cp2;
int opcode, *intptr, value, fwd_port, fwd_host_port;
/* Skip leading whitespace. */
@ -229,21 +237,14 @@ process_config_line(Options *options, const char *host,
if (!*cp || *cp == '\n' || *cp == '#')
return 0;
/* Get the keyword. (Each line is supposed to begin with a
keyword). */
/* Get the keyword. (Each line is supposed to begin with a keyword). */
cp = strtok(cp, WHITESPACE);
{
char *t = cp;
for (; *t != 0; t++)
if ('A' <= *t && *t <= 'Z')
*t = *t - 'A' + 'a'; /* tolower */
}
opcode = parse_token(cp, filename, linenum);
switch (opcode) {
case oBadOption:
return -1; /* don't panic, but count bad options */
/* don't panic, but count bad options */
return -1;
/* NOTREACHED */
case oForwardAgent:
intptr = &options->forward_agent;
@ -419,17 +420,11 @@ parse_int:
fatal("%.200s line %d: Missing argument.", filename, linenum);
if (cp[0] < '0' || cp[0] > '9')
fatal("%.200s line %d: Bad number.", filename, linenum);
#if 0
value = atoi(cp);
#else
{
char *ptr;
value = strtol(cp, &ptr, 0); /* Octal, decimal, or
hex format? */
if (cp == ptr)
fatal("%.200s line %d: Bad number.", filename, linenum);
}
#endif
/* Octal, decimal, or hex format? */
value = strtol(cp, &cp2, 0);
if (cp == cp2)
fatal("%.200s line %d: Bad number.", filename, linenum);
if (*activep && *intptr == -1)
*intptr = value;
break;
@ -506,8 +501,7 @@ parse_int:
*activep = 1;
break;
}
/* Avoid garbage check below, as strtok already returned
NULL. */
/* Avoid garbage check below, as strtok already returned NULL. */
return 0;
case oEscapeChar:
@ -544,9 +538,11 @@ parse_int:
}
/* Reads the config file and modifies the options accordingly. Options should
already be initialized before this call. This never returns if there
is an error. If the file does not exist, this returns immediately. */
/*
* Reads the config file and modifies the options accordingly. Options
* should already be initialized before this call. This never returns if
* there is an error. If the file does not exist, this returns immediately.
*/
void
read_config_file(const char *filename, const char *host, Options *options)
@ -563,8 +559,10 @@ read_config_file(const char *filename, const char *host, Options *options)
debug("Reading configuration data %.200s", filename);
/* Mark that we are now processing the options. This flag is
turned on/off by Host specifications. */
/*
* Mark that we are now processing the options. This flag is turned
* on/off by Host specifications.
*/
active = 1;
linenum = 0;
while (fgets(line, sizeof(line), f)) {
@ -579,10 +577,12 @@ read_config_file(const char *filename, const char *host, Options *options)
filename, bad_options);
}
/* Initializes options to special values that indicate that they have not
yet been set. Read_config_file will only set options with this value.
Options are processed in the following order: command line, user config
file, system config file. Last, fill_default_options is called. */
/*
* Initializes options to special values that indicate that they have not yet
* been set. Read_config_file will only set options with this value. Options
* are processed in the following order: command line, user config file,
* system config file. Last, fill_default_options is called.
*/
void
initialize_options(Options * options)
@ -628,8 +628,10 @@ initialize_options(Options * options)
options->log_level = (LogLevel) - 1;
}
/* Called after processing other sources of option data, this fills those
options for which no value has been specified with their default values. */
/*
* Called after processing other sources of option data, this fills those
* options for which no value has been specified with their default values.
*/
void
fill_default_options(Options * options)

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

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: readconf.h,v 1.4 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: readconf.h,v 1.5 1999/11/25 00:54:59 damien Exp $"); */
#ifndef READCONF_H
#define READCONF_H
@ -85,42 +85,53 @@ typedef struct {
} Options;
/* Initializes options to special values that indicate that they have not
yet been set. Read_config_file will only set options with this value.
Options are processed in the following order: command line, user config
file, system config file. Last, fill_default_options is called. */
/*
* Initializes options to special values that indicate that they have not yet
* been set. Read_config_file will only set options with this value. Options
* are processed in the following order: command line, user config file,
* system config file. Last, fill_default_options is called.
*/
void initialize_options(Options * options);
/* Called after processing other sources of option data, this fills those
options for which no value has been specified with their default values. */
/*
* Called after processing other sources of option data, this fills those
* options for which no value has been specified with their default values.
*/
void fill_default_options(Options * options);
/* Processes a single option line as used in the configuration files.
This only sets those values that have not already been set.
Returns 0 for legal options */
/*
* Processes a single option line as used in the configuration files. This
* only sets those values that have not already been set. Returns 0 for legal
* options
*/
int
process_config_line(Options * options, const char *host,
char *line, const char *filename, int linenum,
int *activep);
/* Reads the config file and modifies the options accordingly. Options should
already be initialized before this call. This never returns if there
is an error. If the file does not exist, this returns immediately. */
/*
* Reads the config file and modifies the options accordingly. Options
* should already be initialized before this call. This never returns if
* there is an error. If the file does not exist, this returns immediately.
*/
void
read_config_file(const char *filename, const char *host,
Options * options);
/* Adds a local TCP/IP port forward to options. Never returns if there
is an error. */
/*
* Adds a local TCP/IP port forward to options. Never returns if there is an
* error.
*/
void
add_local_forward(Options * options, int port, const char *host,
int host_port);
/* Adds a remote TCP/IP port forward to options. Never returns if there
is an error. */
/*
* Adds a remote TCP/IP port forward to options. Never returns if there is
* an error.
*/
void
add_remote_forward(Options * options, int port, const char *host,
int host_port);
#endif /* READCONF_H */

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

@ -14,7 +14,7 @@
*/
#include "includes.h"
RCSID("$Id: readpass.c,v 1.2 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: readpass.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -38,10 +38,12 @@ intr_handler(int sig)
kill(getpid(), sig);
}
/* Reads a passphrase from /dev/tty with echo turned off. Returns the
passphrase (allocated with xmalloc). Exits if EOF is encountered.
The passphrase if read from stdin if from_stdin is true (as is the
case with ssh-keygen). */
/*
* Reads a passphrase from /dev/tty with echo turned off. Returns the
* passphrase (allocated with xmalloc). Exits if EOF is encountered. The
* passphrase if read from stdin if from_stdin is true (as is the case with
* ssh-keygen).
*/
char *
read_passphrase(const char *prompt, int from_stdin)
@ -53,8 +55,10 @@ read_passphrase(const char *prompt, int from_stdin)
if (from_stdin)
f = stdin;
else {
/* Read the passphrase from /dev/tty to make it possible
to ask it even when stdin has been redirected. */
/*
* Read the passphrase from /dev/tty to make it possible to
* ask it even when stdin has been redirected.
*/
f = fopen("/dev/tty", "r");
if (!f) {
/* No controlling terminal and no DISPLAY. Nowhere to read. */
@ -101,8 +105,10 @@ read_passphrase(const char *prompt, int from_stdin)
*strchr(buf, '\n') = 0;
/* Allocate a copy of the passphrase. */
cp = xstrdup(buf);
/* Clear the buffer so we don\'t leave copies of the passphrase
laying around. */
/*
* Clear the buffer so we don\'t leave copies of the passphrase
* laying around.
*/
memset(buf, 0, sizeof(buf));
/* Print a newline since the prompt probably didn\'t have one. */
fprintf(stderr, "\n");

10
rsa.c
Просмотреть файл

@ -35,7 +35,7 @@
*/
#include "includes.h"
RCSID("$Id: rsa.c,v 1.4 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: rsa.c,v 1.5 1999/11/25 00:54:59 damien Exp $");
#include "rsa.h"
#include "ssh.h"
@ -55,9 +55,11 @@ rsa_alive()
return (1);
}
/* Generates RSA public and private keys. This initializes the data
structures; they should be freed with rsa_clear_private_key and
rsa_clear_public_key. */
/*
* Generates RSA public and private keys. This initializes the data
* structures; they should be freed with rsa_clear_private_key and
* rsa_clear_public_key.
*/
void
rsa_generate_key(RSA *prv, RSA *pub, unsigned int bits)

8
rsa.h
Просмотреть файл

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: rsa.h,v 1.4 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: rsa.h,v 1.5 1999/11/25 00:54:59 damien Exp $"); */
#ifndef RSA_H
#define RSA_H
@ -33,8 +33,10 @@
/* Calls SSL RSA_generate_key, only copies to prv and pub */
void rsa_generate_key(RSA * prv, RSA * pub, unsigned int bits);
/* Indicates whether the rsa module is permitted to show messages on
the terminal. */
/*
* Indicates whether the rsa module is permitted to show messages on the
* terminal.
*/
void rsa_set_verbose __P((int verbose));
int rsa_alive __P((void));

20
scp.c
Просмотреть файл

@ -45,7 +45,7 @@
*/
#include "includes.h"
RCSID("$Id: scp.c,v 1.9 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: scp.c,v 1.10 1999/11/25 00:54:59 damien Exp $");
#include "ssh.h"
#include "xmalloc.h"
@ -97,9 +97,11 @@ char *identity = NULL;
/* This is the port to use in contacting the remote site (is non-NULL). */
char *port = NULL;
/* This function executes the given command as the specified user on the given
host. This returns < 0 if execution fails, and >= 0 otherwise.
This assigns the input and output file descriptors on success. */
/*
* This function executes the given command as the specified user on the
* given host. This returns < 0 if execution fails, and >= 0 otherwise. This
* assigns the input and output file descriptors on success.
*/
int
do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
@ -110,8 +112,10 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout)
fprintf(stderr, "Executing: host %s, user %s, command %s\n",
host, remuser ? remuser : "(unspecified)", cmd);
/* Reserve two descriptors so that the real pipes won't get
descriptors 0 and 1 because that will screw up dup2 below. */
/*
* Reserve two descriptors so that the real pipes won't get
* descriptors 0 and 1 because that will screw up dup2 below.
*/
pipe(reserved);
/* Create a socket pair for communicating with ssh. */
@ -970,7 +974,7 @@ run_err(const char *fmt,...)
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: scp.c,v 1.9 1999/11/24 13:26:22 damien Exp $
* $Id: scp.c,v 1.10 1999/11/25 00:54:59 damien Exp $
*/
char *
@ -1142,7 +1146,7 @@ progressmeter(int flag)
(void) gettimeofday(&now, (struct timezone *) 0);
cursize = statbytes;
if (totalbytes != 0) {
ratio = cursize * 100.0 / totalbytes;
ratio = 100.0 * cursize / totalbytes;
ratio = MAX(ratio, 0);
ratio = MIN(ratio, 100);
} else

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

@ -12,7 +12,7 @@
*/
#include "includes.h"
RCSID("$Id: servconf.c,v 1.6 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: servconf.c,v 1.7 1999/11/25 00:54:59 damien Exp $");
#include "ssh.h"
#include "servconf.h"
@ -212,8 +212,10 @@ static struct {
{ NULL, 0 }
};
/* Returns the number of the token pointed to by cp of length len.
Never returns if the token is not known. */
/*
* Returns the number of the token pointed to by cp of length len. Never
* returns if the token is not known.
*/
static ServerOpCodes
parse_token(const char *cp, const char *filename,
@ -222,7 +224,7 @@ parse_token(const char *cp, const char *filename,
unsigned int i;
for (i = 0; keywords[i].name; i++)
if (strcmp(cp, keywords[i].name) == 0)
if (strcasecmp(cp, keywords[i].name) == 0)
return keywords[i].opcode;
fprintf(stderr, "%s: line %d: Bad configuration option: %s\n",
@ -254,13 +256,6 @@ read_server_config(ServerOptions *options, const char *filename)
if (!*cp || *cp == '#')
continue;
cp = strtok(cp, WHITESPACE);
{
char *t = cp;
for (; *t != 0; t++)
if ('A' <= *t && *t <= 'Z')
*t = *t - 'A' + 'a'; /* tolower */
}
opcode = parse_token(cp, filename, linenum);
switch (opcode) {
case sBadOption:

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

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: servconf.h,v 1.4 1999/11/24 13:26:22 damien Exp $"); */
/* RCSID("$Id: servconf.h,v 1.5 1999/11/25 00:54:59 damien Exp $"); */
#ifndef SERVCONF_H
#define SERVCONF_H
@ -84,12 +84,16 @@ typedef struct {
unsigned int num_deny_groups;
char *deny_groups[MAX_DENY_GROUPS];
} ServerOptions;
/* Initializes the server options to special values that indicate that they
have not yet been set. */
/*
* Initializes the server options to special values that indicate that they
* have not yet been set.
*/
void initialize_server_options(ServerOptions * options);
/* Reads the server configuration file. This only sets the values for those
options that have the special value indicating they have not been set. */
/*
* Reads the server configuration file. This only sets the values for those
* options that have the special value indicating they have not been set.
*/
void read_server_config(ServerOptions * options, const char *filename);
/* Sets values for those values that have not yet been set. */

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

@ -33,8 +33,10 @@ static int connection_out; /* Connection to client (output). */
static unsigned int buffer_high;/* "Soft" max buffer size. */
static int max_fd; /* Max file descriptor number for select(). */
/* This SIGCHLD kludge is used to detect when the child exits. The server
will exit after that, as soon as forwarded connections have terminated. */
/*
* This SIGCHLD kludge is used to detect when the child exits. The server
* will exit after that, as soon as forwarded connections have terminated.
*/
static int child_pid; /* Pid of the child. */
static volatile int child_terminated; /* The child has terminated. */
@ -87,9 +89,11 @@ process_buffered_input_packets()
break;
case SSH_CMSG_EOF:
/* Eof from the client. The stdin descriptor to
the program will be closed when all buffered
data has drained. */
/*
* 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;
@ -140,13 +144,15 @@ process_buffered_input_packets()
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. */
/*
* 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);
}
@ -230,14 +236,18 @@ retry_select:
/* Initialize select() masks. */
FD_ZERO(readset);
/* Read packets from the client unless we have too much buffered
stdin or channel data. */
/*
* Read packets from the client unless we have too much buffered
* stdin or channel data.
*/
if (buffer_len(&stdin_buffer) < 4096 &&
channel_not_very_much_buffered_data())
FD_SET(connection_in, readset);
/* If there is not too much data already buffered going to the
client, try to get some more data from the program. */
/*
* If there is not too much data already buffered going to the
* client, try to get some more data from the program.
*/
if (packet_not_very_much_data_to_write()) {
if (!fdout_eof)
FD_SET(fdout, readset);
@ -249,8 +259,10 @@ retry_select:
/* Set masks for channel descriptors. */
channel_prepare_select(readset, writeset);
/* If we have buffered packet data going to the client, mark that
descriptor. */
/*
* If we have buffered packet data going to the client, mark that
* descriptor.
*/
if (packet_have_data_to_write())
FD_SET(connection_out, writeset);
@ -263,8 +275,10 @@ retry_select:
if (channel_max_fd() > max_fd)
max_fd = channel_max_fd();
/* If child has terminated and there is enough buffer space to
read from it, then read as much as is available and exit. */
/*
* If child has terminated and there is enough buffer space to read
* from it, then read as much as is available and exit.
*/
if (child_terminated && packet_not_very_much_data_to_write())
if (max_time_milliseconds == 0)
max_time_milliseconds = 100;
@ -305,9 +319,10 @@ process_input(fd_set * readset)
verbose("Connection closed by remote host.");
fatal_cleanup();
}
/* There is a kernel bug on Solaris that causes select to
sometimes wake up even though there is no data
available. */
/*
* There is a kernel bug on Solaris that causes select to
* sometimes wake up even though there is no data available.
*/
if (len < 0 && errno == EAGAIN)
len = 0;
@ -456,11 +471,12 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
buffer_init(&stdout_buffer);
buffer_init(&stderr_buffer);
/* If we have no separate fderr (which is the case when we have a
pty - there we cannot make difference between data sent to
stdout and stderr), indicate that we have seen an EOF from
stderr. This way we don\'t need to check the descriptor
everywhere. */
/*
* If we have no separate fderr (which is the case when we have a pty
* - there we cannot make difference between data sent to stdout and
* stderr), indicate that we have seen an EOF from stderr. This way
* we don\'t need to check the descriptor everywhere.
*/
if (fderr == -1)
fderr_eof = 1;
@ -471,8 +487,10 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
/* Process buffered packets from the client. */
process_buffered_input_packets();
/* If we have received eof, and there is no more pending
input data, cause a real eof by closing fdin. */
/*
* If we have received eof, and there is no more pending
* input data, cause a real eof by closing fdin.
*/
if (stdin_eof && fdin != -1 && buffer_len(&stdin_buffer) == 0) {
#ifdef USE_PIPES
close(fdin);
@ -484,16 +502,16 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
#endif
fdin = -1;
}
/* Make packets from buffered stderr data to send to the
client. */
/* Make packets from buffered stderr data to send to the client. */
make_packets_from_stderr_data();
/* Make packets from buffered stdout data to send to the
client. If there is very little to send, this arranges
to not send them now, but to wait a short while to see
if we are getting more data. This is necessary, as some
systems wake up readers from a pty after each separate
character. */
/*
* Make packets from buffered stdout data to send to the
* client. If there is very little to send, this arranges to
* not send them now, but to wait a short while to see if we
* are getting more data. This is necessary, as some systems
* wake up readers from a pty after each separate character.
*/
max_time_milliseconds = 0;
stdout_buffer_bytes = buffer_len(&stdout_buffer);
if (stdout_buffer_bytes != 0 && stdout_buffer_bytes < 256 &&
@ -510,9 +528,11 @@ server_loop(int pid, int fdin_arg, int fdout_arg, int fderr_arg)
if (packet_not_very_much_data_to_write())
channel_output_poll();
/* Bail out of the loop if the program has closed its
output descriptors, and we have no more data to send to
the client, and there is no pending buffered data. */
/*
* Bail out of the loop if the program has closed its output
* descriptors, and we have no more data to send to the
* client, and there is no pending buffered data.
*/
if (fdout_eof && fderr_eof && !packet_have_data_to_write() &&
buffer_len(&stdout_buffer) == 0 && buffer_len(&stderr_buffer) == 0) {
if (!channel_still_open())
@ -604,11 +624,13 @@ quit:
packet_send();
packet_write_wait();
/* Wait for exit confirmation. Note that there might be
other packets coming before it; however, the program
has already died so we just ignore them. The client is
supposed to respond with the confirmation when it
receives the exit status. */
/*
* Wait for exit confirmation. Note that there might be
* other packets coming before it; however, the program has
* already died so we just ignore them. The client is
* supposed to respond with the confirmation when it receives
* the exit status.
*/
do {
int plen;
type = packet_read(&plen);

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

@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 22 23:55:14 1995 ylo
.\"
.\" $Id: ssh-add.1,v 1.4 1999/11/17 06:29:08 damien Exp $
.\" $Id: ssh-add.1,v 1.5 1999/11/25 00:54:59 damien Exp $
.\"
.Dd September 25, 1999
.Dt SSH-ADD 1
@ -71,8 +71,11 @@ terminal if it was run from a terminal. If
.Nm
does not have a terminal associated with it but
.Ev DISPLAY
is set, it
will open an X11 window to read the passphrase. This is particularly
and
.Ev SSH_ASKPASS
are set, it will execute the program specified by
.Ev SSH_ASKPASS
and open an X11 window to read the passphrase. This is particularly
useful when calling
.Nm
from a

167
ssh-add.c
Просмотреть файл

@ -7,7 +7,7 @@
*/
#include "includes.h"
RCSID("$Id: ssh-add.c,v 1.13 1999/11/24 13:26:22 damien Exp $");
RCSID("$Id: ssh-add.c,v 1.14 1999/11/25 00:54:59 damien Exp $");
#include "rsa.h"
#include "ssh.h"
@ -15,10 +15,6 @@ RCSID("$Id: ssh-add.c,v 1.13 1999/11/24 13:26:22 damien Exp $");
#include "authfd.h"
#include "fingerprint.h"
#ifdef USE_EXTERNAL_ASKPASS
int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment);
#endif /* USE_EXTERNAL_ASKPASS */
#ifdef HAVE___PROGNAME
extern char *__progname;
#else /* HAVE___PROGNAME */
@ -54,13 +50,53 @@ delete_all(AuthenticationConnection *ac)
fprintf(stderr, "Failed to remove all identitities.\n");
}
char *
ssh_askpass(char *askpass, char *msg)
{
pid_t pid;
size_t len;
char *nl, *pass;
int p[2], status;
char buf[1024];
if (askpass == NULL)
fatal("internal error: askpass undefined");
if (pipe(p) < 0)
fatal("ssh_askpass: pipe: %s", strerror(errno));
if ((pid = fork()) < 0)
fatal("ssh_askpass: fork: %s", strerror(errno));
if (pid == 0) {
close(p[0]);
if (dup2(p[1], STDOUT_FILENO) < 0)
fatal("ssh_askpass: dup2: %s", strerror(errno));
execlp(askpass, askpass, msg, (char *) 0);
fatal("ssh_askpass: exec(%s): %s", askpass, strerror(errno));
}
close(p[1]);
len = read(p[0], buf, sizeof buf);
close(p[0]);
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR)
break;
if (len <= 1)
return xstrdup("");
nl = strchr(buf, '\n');
if (nl)
*nl = '\0';
pass = xstrdup(buf);
memset(buf, 0, sizeof(buf));
return pass;
}
void
add_file(AuthenticationConnection *ac, const char *filename)
{
RSA *key;
RSA *public_key;
char *saved_comment, *comment;
char *saved_comment, *comment, *askpass = NULL;
char buf[1024], msg[1024];
int success;
int interactive = isatty(STDIN_FILENO);
key = RSA_new();
public_key = RSA_new();
@ -70,29 +106,26 @@ add_file(AuthenticationConnection *ac, const char *filename)
}
RSA_free(public_key);
if (!interactive && getenv("DISPLAY"))
askpass = getenv("SSH_ASKPASS");
/* At first, try empty passphrase */
success = load_private_key(filename, "", key, &comment);
if (!success) {
printf("Need passphrase for %s (%s).\n", filename, saved_comment);
if (!isatty(STDIN_FILENO)) {
#ifdef USE_EXTERNAL_ASKPASS
int prompts = 3;
while (prompts && !success) {
success = askpass(filename, key, saved_comment, &comment);
prompts--;
}
if (!success) {
xfree(saved_comment);
return;
}
#else /* !USE_EXTERNAL_ASKPASS */
xfree(saved_comment);
return;
#endif /* USE_EXTERNAL_ASKPASS */
printf("Need passphrase for %.200s\n", filename);
if (!interactive && askpass == NULL) {
xfree(saved_comment);
return;
}
while (!success) {
char *pass = read_passphrase("Enter passphrase: ", 1);
snprintf(msg, sizeof msg, "Enter passphrase for %.200s", saved_comment);
for (;;) {
char *pass;
if (interactive) {
snprintf(buf, sizeof buf, "%s: ", msg);
pass = read_passphrase(buf, 1);
} else {
pass = ssh_askpass(askpass, msg);
}
if (strcmp(pass, "") == 0) {
xfree(pass);
xfree(saved_comment);
@ -103,7 +136,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
xfree(pass);
if (success)
break;
printf("Bad passphrase.\n");
strlcpy(msg, "Bad passphrase, try again", sizeof msg);
}
}
xfree(saved_comment);
@ -222,85 +255,3 @@ main(int argc, char **argv)
ssh_close_authentication_connection(ac);
exit(0);
}
#ifdef USE_EXTERNAL_ASKPASS
int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment)
{
int pipes[2];
char buf[1024];
int tmp;
pid_t child;
FILE *pipef;
/* Check that we are X11-capable */
if (getenv("DISPLAY") == NULL)
exit(1);
if (pipe(pipes) == -1) {
fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno));
exit(1);
}
if (fflush(NULL) == EOF) {
fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno));
exit(1);
}
child = fork();
if (child == -1) {
fprintf(stderr, "Cannot fork: %s\n", strerror(errno));
exit(1);
}
if (child == 0) {
/* In child */
close(pipes[0]);
if (dup2(pipes[1], 1) ==-1) {
fprintf(stderr, "dup2 failed: %s\n", strerror(errno));
exit(1);
}
tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s", saved_comment);
/* skip the prompt if it won't fit */
if ((tmp < 0) || (tmp >= sizeof(buf)))
tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0);
else
tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0);
/* Shouldn't get this far */
fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno));
exit(1);
}
/* In parent */
close(pipes[1]);
if ((pipef = fdopen(pipes[0], "r")) == NULL) {
fprintf(stderr, "fdopen failed: %s\n", strerror(errno));
exit(1);
}
/* Read passphrase back from child, abort if none presented */
if(fgets(buf, sizeof(buf), pipef) == NULL)
exit(1);
fclose(pipef);
if (strchr(buf, '\n'))
*strchr(buf, '\n') = 0;
if (waitpid(child, NULL, 0) == -1) {
fprintf(stderr, "Waiting for child failed: %s\n",
strerror(errno));
exit(1);
}
/* Try password as it was presented */
tmp = load_private_key(filename, buf, key, comment);
memset(buf, 0, sizeof(buf));
return(tmp);
}
#endif /* USE_EXTERNAL_ASKPASS */

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

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-agent.c,v 1.22 1999/11/24 00:26:03 deraadt Exp $ */
/* $OpenBSD: ssh-agent.c,v 1.23 1999/11/24 19:53:51 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -9,7 +9,7 @@
*/
#include "includes.h"
RCSID("$OpenBSD: ssh-agent.c,v 1.22 1999/11/24 00:26:03 deraadt Exp $");
RCSID("$OpenBSD: ssh-agent.c,v 1.23 1999/11/24 19:53:51 markus Exp $");
#include "ssh.h"
#include "rsa.h"
@ -189,10 +189,12 @@ process_remove_identity(SocketEntry *e)
/* Check if we have the key. */
for (i = 0; i < num_identities; i++)
if (BN_cmp(identities[i].key->n, n) == 0) {
/* We have this key. Free the old key. Since we
don\'t want to leave empty slots in the middle
of the array, we actually free the key there
and copy data from the last entry. */
/*
* We have this key. Free the old key. Since we
* don\'t want to leave empty slots in the middle of
* the array, we actually free the key there and copy
* data from the last entry.
*/
RSA_free(identities[i].key);
xfree(identities[i].comment);
if (i < num_identities - 1)
@ -291,8 +293,10 @@ process_add_identity(SocketEntry *e)
/* Check if we already have the key. */
for (i = 0; i < num_identities; i++)
if (BN_cmp(identities[i].key->n, k->n) == 0) {
/* We already have this key. Clear and free the
new data and return success. */
/*
* We already have this key. Clear and free the new
* data and return success.
*/
RSA_free(k);
xfree(identities[num_identities].comment);
@ -511,11 +515,7 @@ main(int ac, char **av)
__progname);
exit(1);
}
#if defined(__GNU_LIBRARY__)
while ((ch = getopt(ac, av, "+cks")) != -1) {
#else
while ((ch = getopt(ac, av, "cks")) != -1) {
#endif /* defined(__GNU_LIBRARY__) */
switch (ch) {
case 'c':
if (s_flag)
@ -579,8 +579,10 @@ main(int ac, char **av)
snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
parent_pid);
/* Create socket early so it will exist before command gets run
from the parent. */
/*
* Create socket early so it will exist before command gets run from
* the parent.
*/
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
perror("socket");
@ -597,9 +599,10 @@ main(int ac, char **av)
perror("listen");
cleanup_exit(1);
}
/* Fork, and have the parent execute the command, if any, or
present the socket data. The child continues as the
authentication agent. */
/*
* Fork, and have the parent execute the command, if any, or present
* the socket data. The child continues as the authentication agent.
*/
pid = fork();
if (pid == -1) {
perror("fork");

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

@ -7,7 +7,7 @@
*/
#include "includes.h"
RCSID("$Id: ssh-keygen.c,v 1.9 1999/11/24 13:26:23 damien Exp $");
RCSID("$Id: ssh-keygen.c,v 1.10 1999/11/25 00:54:59 damien Exp $");
#include "rsa.h"
#include "ssh.h"
@ -20,16 +20,19 @@ RSA *private_key;
/* Generated public key. */
RSA *public_key;
/* Number of bits in the RSA key. This value can be changed on the command
line. */
/* Number of bits in the RSA key. This value can be changed on the command line. */
int bits = 1024;
/* Flag indicating that we just want to change the passphrase. This can be
set on the command line. */
/*
* Flag indicating that we just want to change the passphrase. This can be
* set on the command line.
*/
int change_passphrase = 0;
/* Flag indicating that we just want to change the comment. This can be set
on the command line. */
/*
* Flag indicating that we just want to change the comment. This can be set
* on the command line.
*/
int change_comment = 0;
int quiet = 0;
@ -136,13 +139,10 @@ do_change_passphrase(struct passwd *pw)
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
/* Check if the file exists. */
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
/* Try to load the public key from the file the verify that it is
readable and of the proper format. */
public_key = RSA_new();
if (!load_public_key(identity_file, public_key, NULL)) {
printf("%s is not a valid key file.\n", identity_file);
@ -154,19 +154,16 @@ do_change_passphrase(struct passwd *pw)
/* Try to load the file with empty passphrase. */
private_key = RSA_new();
if (!load_private_key(identity_file, "", private_key, &comment)) {
/* Read passphrase from the user. */
if (identity_passphrase)
old_passphrase = xstrdup(identity_passphrase);
else
old_passphrase = read_passphrase("Enter old passphrase: ", 1);
/* Try to load using the passphrase. */
if (!load_private_key(identity_file, old_passphrase, private_key, &comment)) {
memset(old_passphrase, 0, strlen(old_passphrase));
xfree(old_passphrase);
printf("Bad passphrase.\n");
exit(1);
}
/* Destroy the passphrase. */
memset(old_passphrase, 0, strlen(old_passphrase));
xfree(old_passphrase);
}
@ -230,24 +227,24 @@ do_change_comment(struct passwd *pw)
if (!have_identity)
ask_filename(pw, "Enter file in which the key is");
/* Check if the file exists. */
if (stat(identity_file, &st) < 0) {
perror(identity_file);
exit(1);
}
/* Try to load the public key from the file the verify that it is
readable and of the proper format. */
/*
* Try to load the public key from the file the verify that it is
* readable and of the proper format.
*/
public_key = RSA_new();
if (!load_public_key(identity_file, public_key, NULL)) {
printf("%s is not a valid key file.\n", identity_file);
exit(1);
}
private_key = RSA_new();
/* Try to load the file with empty passphrase. */
if (load_private_key(identity_file, "", private_key, &comment))
passphrase = xstrdup("");
else {
/* Read passphrase from the user. */
if (identity_passphrase)
passphrase = xstrdup(identity_passphrase);
else if (identity_new_passphrase)
@ -274,7 +271,6 @@ do_change_comment(struct passwd *pw)
RSA_free(private_key);
exit(1);
}
/* Remove terminating newline from comment. */
if (strchr(new_comment, '\n'))
*strchr(new_comment, '\n') = 0;
}
@ -289,13 +285,10 @@ do_change_comment(struct passwd *pw)
xfree(comment);
exit(1);
}
/* Destroy the passphrase and the private key in memory. */
memset(passphrase, 0, strlen(passphrase));
xfree(passphrase);
RSA_free(private_key);
/* Save the public key in text format in a file with the same name
but .pub appended. */
strlcat(identity_file, ".pub", sizeof(identity_file));
f = fopen(identity_file, "w");
if (!f) {
@ -343,21 +336,18 @@ main(int ac, char **av)
/* check if RSA support exists */
if (rsa_alive() == 0) {
extern char *__progname;
fprintf(stderr,
"%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
__progname);
exit(1);
}
/* Get user\'s passwd structure. We need this for the home
directory. */
/* we need this for the home * directory. */
pw = getpwuid(getuid());
if (!pw) {
printf("You don't exist, go away!\n");
exit(1);
}
/* Parse command line arguments. */
while ((opt = getopt(ac, av, "qpclb:f:P:N:C:")) != EOF) {
switch (opt) {
case 'b':
@ -416,14 +406,8 @@ main(int ac, char **av)
}
if (print_fingerprint)
do_fingerprint(pw);
/* If the user requested to change the passphrase, do it now.
This function never returns. */
if (change_passphrase)
do_change_passphrase(pw);
/* If the user requested to change the comment, do it now. This
function never returns. */
if (change_comment)
do_change_comment(pw);
@ -484,11 +468,10 @@ passphrase_again:
xfree(passphrase2);
}
/* Create default commend field for the passphrase. The user can
later edit this field. */
if (identity_comment) {
strlcpy(comment, identity_comment, sizeof(comment));
} else {
/* Create default commend field for the passphrase. */
if (gethostname(hostname, sizeof(hostname)) < 0) {
perror("gethostname");
exit(1);
@ -515,8 +498,6 @@ passphrase_again:
if (!quiet)
printf("Your identification has been saved in %s.\n", identity_file);
/* Save the public key in text format in a file with the same name
but .pub appended. */
strlcat(identity_file, ".pub", sizeof(identity_file));
f = fopen(identity_file, "w");
if (!f) {

4
ssh.1
Просмотреть файл

@ -9,7 +9,7 @@
.\"
.\" Created: Sat Apr 22 21:55:14 1995 ylo
.\"
.\" $Id: ssh.1,v 1.9 1999/11/24 13:26:23 damien Exp $
.\" $Id: ssh.1,v 1.10 1999/11/25 00:54:59 damien Exp $
.\"
.Dd September 25, 1999
.Dt SSH 1
@ -293,7 +293,7 @@ disables any escapes and makes the session fully transparent.
.It Fl f
Requests
.Nm
to go to background after authentication. This is useful
to go to background just before command execution. This is useful
if
.Nm
is going to ask for passwords or passphrases, but the user

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

@ -11,7 +11,7 @@
*/
#include "includes.h"
RCSID("$Id: ssh.c,v 1.11 1999/11/24 13:26:23 damien Exp $");
RCSID("$Id: ssh.c,v 1.12 1999/11/25 00:54:59 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -30,35 +30,43 @@ const char *__progname = "ssh";
/* Flag indicating whether debug mode is on. This can be set on the command line. */
int debug_flag = 0;
/* Flag indicating whether to allocate a pseudo tty. This can be set on the command
line, and is automatically set if no command is given on the command line. */
int tty_flag = 0;
/* Flag indicating that nothing should be read from stdin. This can be set
on the command line. */
/*
* Flag indicating that nothing should be read from stdin. This can be set
* on the command line.
*/
int stdin_null_flag = 0;
/* Flag indicating that ssh should fork after authentication. This is useful
so that the pasphrase can be entered manually, and then ssh goes to the
background. */
/*
* Flag indicating that ssh should fork after authentication. This is useful
* so that the pasphrase can be entered manually, and then ssh goes to the
* background.
*/
int fork_after_authentication_flag = 0;
/* General data structure for command line options and options configurable
in configuration files. See readconf.h. */
/*
* General data structure for command line options and options configurable
* in configuration files. See readconf.h.
*/
Options options;
/* Name of the host we are connecting to. This is the name given on the
command line, or the HostName specified for the user-supplied name
in a configuration file. */
/*
* Name of the host we are connecting to. This is the name given on the
* command line, or the HostName specified for the user-supplied name in a
* configuration file.
*/
char *host;
/* socket address the host resolves to */
struct sockaddr_in hostaddr;
/* Flag to indicate that we have received a window change signal which has
not yet been processed. This will cause a message indicating the new
window size to be sent to the server a little later. This is volatile
because this is updated in a signal handler. */
/*
* Flag to indicate that we have received a window change signal which has
* not yet been processed. This will cause a message indicating the new
* window size to be sent to the server a little later. This is volatile
* because this is updated in a signal handler.
*/
volatile int received_window_change_signal = 0;
/* Value of argv[0] (set in the main program). */
@ -165,8 +173,10 @@ main(int ac, char **av)
uid_t original_effective_uid;
int plen;
/* Save the original real uid. It will be needed later
(uid-swapping may clobber the real uid). */
/*
* Save the original real uid. It will be needed later (uid-swapping
* may clobber the real uid).
*/
original_real_uid = getuid();
original_effective_uid = geteuid();
@ -177,18 +187,21 @@ main(int ac, char **av)
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
fatal("setrlimit failed: %.100s", strerror(errno));
}
/* Use uid-swapping to give up root privileges for the duration of
option processing. We will re-instantiate the rights when we
are ready to create the privileged port, and will permanently
drop them when the port has been created (actually, when the
connection has been made, as we may need to create the port
several times). */
/*
* Use uid-swapping to give up root privileges for the duration of
* option processing. We will re-instantiate the rights when we are
* ready to create the privileged port, and will permanently drop
* them when the port has been created (actually, when the connection
* has been made, as we may need to create the port several times).
*/
temporarily_use_uid(original_real_uid);
/* Set our umask to something reasonable, as some files are
created with the default umask. This will make them
world-readable but writable only by the owner, which is ok for
all files for which we don't set the modes explicitly. */
/*
* Set our umask to something reasonable, as some files are created
* with the default umask. This will make them world-readable but
* writable only by the owner, which is ok for all files for which we
* don't set the modes explicitly.
*/
umask(022);
/* Save our own name. */
@ -387,10 +400,11 @@ main(int ac, char **av)
/* Initialize the command to execute on remote host. */
buffer_init(&command);
/* Save the command to execute on the remote host in a buffer.
There is no limit on the length of the command, except by the
maximum packet size. Also sets the tty flag if there is no
command. */
/*
* Save the command to execute on the remote host in a buffer. There
* is no limit on the length of the command, except by the maximum
* packet size. Also sets the tty flag if there is no command.
*/
if (optind == ac) {
/* No command specified - execute shell on a tty. */
tty_flag = 1;
@ -474,11 +488,15 @@ main(int ac, char **av)
options.rhosts_authentication = 0;
options.rhosts_rsa_authentication = 0;
}
/* If using rsh has been selected, exec it now (without trying
anything else). Note that we must release privileges first. */
/*
* If using rsh has been selected, exec it now (without trying
* anything else). Note that we must release privileges first.
*/
if (options.use_rsh) {
/* Restore our superuser privileges. This must be done
before permanently setting the uid. */
/*
* Restore our superuser privileges. This must be done
* before permanently setting the uid.
*/
restore_uid();
/* Switch to the original uid permanently. */
@ -491,8 +509,10 @@ main(int ac, char **av)
/* Restore our superuser privileges. */
restore_uid();
/* Open a connection to the remote host. This needs root
privileges if rhosts_{rsa_}authentication is enabled. */
/*
* Open a connection to the remote host. This needs root privileges
* if rhosts_{rsa_}authentication is enabled.
*/
ok = ssh_connect(host, &hostaddr, options.port,
options.connection_attempts,
@ -501,31 +521,38 @@ main(int ac, char **av)
original_real_uid,
options.proxy_command);
/* If we successfully made the connection, load the host private
key in case we will need it later for combined rsa-rhosts
authentication. This must be done before releasing extra
privileges, because the file is only readable by root. */
/*
* If we successfully made the connection, load the host private key
* in case we will need it later for combined rsa-rhosts
* authentication. This must be done before releasing extra
* privileges, because the file is only readable by root.
*/
if (ok) {
host_private_key = RSA_new();
if (load_private_key(HOST_KEY_FILE, "", host_private_key, NULL))
host_private_key_loaded = 1;
}
/* Get rid of any extra privileges that we may have. We will no
longer need them. Also, extra privileges could make it very
hard to read identity files and other non-world-readable files
from the user's home directory if it happens to be on a NFS
volume where root is mapped to nobody. */
/* Note that some legacy systems need to postpone the following
call to permanently_set_uid() until the private hostkey is
destroyed with RSA_free(). Otherwise the calling user could
ptrace() the process, read the private hostkey and impersonate
the host. OpenBSD does not allow ptracing of setuid processes. */
/*
* Get rid of any extra privileges that we may have. We will no
* longer need them. Also, extra privileges could make it very hard
* to read identity files and other non-world-readable files from the
* user's home directory if it happens to be on a NFS volume where
* root is mapped to nobody.
*/
/*
* Note that some legacy systems need to postpone the following call
* to permanently_set_uid() until the private hostkey is destroyed
* with RSA_free(). Otherwise the calling user could ptrace() the
* process, read the private hostkey and impersonate the host.
* OpenBSD does not allow ptracing of setuid processes.
*/
permanently_set_uid(original_real_uid);
/* Now that we are back to our own permissions, create ~/.ssh
directory if it doesn\'t already exist. */
/*
* Now that we are back to our own permissions, create ~/.ssh
* directory if it doesn\'t already exist.
*/
snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, SSH_USER_DIR);
if (stat(buf, &st) < 0)
if (mkdir(buf, 0755) < 0)
@ -569,15 +596,6 @@ main(int ac, char **av)
/* Close connection cleanly after attack. */
cipher_attack_detected = packet_disconnect;
/* If requested, fork and let ssh continue in the background. */
if (fork_after_authentication_flag) {
int ret = fork();
if (ret == -1)
fatal("fork failed: %.100s", strerror(errno));
if (ret != 0)
exit(0);
setsid();
}
/* Enable compression if requested. */
if (options.compression) {
debug("Requesting compression at level %d.", options.compression_level);
@ -653,12 +671,14 @@ main(int ac, char **av)
if (f)
pclose(f);
#endif /* XAUTH_PATH */
/* If we didn't get authentication data, just make up some
data. The forwarding code will check the validity of
the response anyway, and substitute this data. The X11
server, however, will ignore this fake data and use
whatever authentication mechanisms it was using
otherwise for the local connection. */
/*
* If we didn't get authentication data, just make up some
* data. The forwarding code will check the validity of the
* response anyway, and substitute this data. The X11
* server, however, will ignore this fake data and use
* whatever authentication mechanisms it was using otherwise
* for the local connection.
*/
if (!got_data) {
u_int32_t rand = 0;
@ -670,8 +690,10 @@ main(int ac, char **av)
rand >>= 8;
}
}
/* Got local authentication reasonable information.
Request forwarding with authentication spoofing. */
/*
* Got local authentication reasonable information. Request
* forwarding with authentication spoofing.
*/
debug("Requesting X11 forwarding with authentication spoofing.");
x11_request_forwarding_with_spoofing(proto, data);
@ -728,8 +750,15 @@ main(int ac, char **av)
options.remote_forwards[i].host_port);
}
/* If a command was specified on the command line, execute the
command now. Otherwise request the server to start a shell. */
/* If requested, let ssh continue in the background. */
if (fork_after_authentication_flag)
if (daemon(1, 1) < 0)
fatal("daemon() failed: %.200s", strerror(errno));
/*
* If a command was specified on the command line, execute the
* command now. Otherwise request the server to start a shell.
*/
if (buffer_len(&command) > 0) {
int len = buffer_len(&command);
if (len > 900)

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

@ -13,7 +13,7 @@
*
*/
/* RCSID("$Id: ssh.h,v 1.15 1999/11/24 13:26:23 damien Exp $"); */
/* RCSID("$Id: ssh.h,v 1.16 1999/11/25 00:54:59 damien Exp $"); */
#ifndef SSH_H
#define SSH_H
@ -25,9 +25,11 @@
#include "rsa.h"
#include "cipher.h"
/* The default cipher used if IDEA is not supported by the remote host.
It is recommended that this be one of the mandatory ciphers (DES, 3DES),
though that is not required. */
/*
* The default cipher used if IDEA is not supported by the remote host. It is
* recommended that this be one of the mandatory ciphers (DES, 3DES), though
* that is not required.
*/
#define SSH_FALLBACK_CIPHER SSH_CIPHER_3DES
/* Cipher used for encrypting authentication files. */
@ -39,20 +41,28 @@
/* Maximum number of TCP/IP ports forwarded per direction. */
#define SSH_MAX_FORWARDS_PER_DIRECTION 100
/* Maximum number of RSA authentication identity files that can be specified
in configuration files or on the command line. */
/*
* Maximum number of RSA authentication identity files that can be specified
* in configuration files or on the command line.
*/
#define SSH_MAX_IDENTITY_FILES 100
/* Major protocol version. Different version indicates major incompatiblity
that prevents communication. */
/*
* Major protocol version. Different version indicates major incompatiblity
* that prevents communication.
*/
#define PROTOCOL_MAJOR 1
/* Minor protocol version. Different version indicates minor incompatibility
that does not prevent interoperation. */
/*
* Minor protocol version. Different version indicates minor incompatibility
* that does not prevent interoperation.
*/
#define PROTOCOL_MINOR 5
/* Name for the service. The port named by this service overrides the default
port if present. */
/*
* Name for the service. The port named by this service overrides the
* default port if present.
*/
#define SSH_SERVICE_NAME "ssh"
#ifndef ETCDIR
@ -63,16 +73,16 @@
#define PIDDIR "/var/run"
#endif /* PIDDIR */
/* System-wide file containing host keys of known hosts. This file should be
world-readable. */
/*
* System-wide file containing host keys of known hosts. This file should be
* world-readable.
*/
#define SSH_SYSTEM_HOSTFILE ETCDIR "/ssh_known_hosts"
/* HOST_KEY_FILE /etc/ssh_host_key,
SERVER_CONFIG_FILE /etc/sshd_config,
and HOST_CONFIG_FILE /etc/ssh_config
are all defined in Makefile.in. Of these, ssh_host_key should be readable
only by root, whereas ssh_config should be world-readable. */
/*
* Of these, ssh_host_key must be readable only by root, whereas ssh_config
* should be world-readable.
*/
#define HOST_KEY_FILE ETCDIR "/ssh_host_key"
#define SERVER_CONFIG_FILE ETCDIR "/sshd_config"
#define HOST_CONFIG_FILE ETCDIR "/ssh_config"
@ -89,73 +99,95 @@ only by root, whereas ssh_config should be world-readable. */
#define ASKPASS_PROGRAM "/usr/lib/ssh/ssh-askpass"
#endif /* ASKPASS_PROGRAM */
/* The process id of the daemon listening for connections is saved
here to make it easier to kill the correct daemon when necessary. */
/*
* The process id of the daemon listening for connections is saved here to
* make it easier to kill the correct daemon when necessary.
*/
#define SSH_DAEMON_PID_FILE PIDDIR "/sshd.pid"
/* The directory in user\'s home directory in which the files reside.
The directory should be world-readable (though not all files are). */
/*
* The directory in user\'s home directory in which the files reside. The
* directory should be world-readable (though not all files are).
*/
#define SSH_USER_DIR ".ssh"
/* Per-user file containing host keys of known hosts. This file need
not be readable by anyone except the user him/herself, though this does
not contain anything particularly secret. */
/*
* Per-user file containing host keys of known hosts. This file need not be
* readable by anyone except the user him/herself, though this does not
* contain anything particularly secret.
*/
#define SSH_USER_HOSTFILE "~/.ssh/known_hosts"
/* Name of the default file containing client-side authentication key.
This file should only be readable by the user him/herself. */
/*
* Name of the default file containing client-side authentication key. This
* file should only be readable by the user him/herself.
*/
#define SSH_CLIENT_IDENTITY ".ssh/identity"
/* Configuration file in user\'s home directory. This file need not be
readable by anyone but the user him/herself, but does not contain
anything particularly secret. If the user\'s home directory resides
on an NFS volume where root is mapped to nobody, this may need to be
world-readable. */
/*
* Configuration file in user\'s home directory. This file need not be
* readable by anyone but the user him/herself, but does not contain anything
* particularly secret. If the user\'s home directory resides on an NFS
* volume where root is mapped to nobody, this may need to be world-readable.
*/
#define SSH_USER_CONFFILE ".ssh/config"
/* File containing a list of those rsa keys that permit logging in as
this user. This file need not be
readable by anyone but the user him/herself, but does not contain
anything particularly secret. If the user\'s home directory resides
on an NFS volume where root is mapped to nobody, this may need to be
world-readable. (This file is read by the daemon which is running as
root.) */
/*
* File containing a list of those rsa keys that permit logging in as this
* user. This file need not be readable by anyone but the user him/herself,
* but does not contain anything particularly secret. If the user\'s home
* directory resides on an NFS volume where root is mapped to nobody, this
* may need to be world-readable. (This file is read by the daemon which is
* running as root.)
*/
#define SSH_USER_PERMITTED_KEYS ".ssh/authorized_keys"
/* Per-user and system-wide ssh "rc" files. These files are executed with
/bin/sh before starting the shell or command if they exist. They
will be passed "proto cookie" as arguments if X11 forwarding with
spoofing is in use. xauth will be run if neither of these exists. */
/*
* Per-user and system-wide ssh "rc" files. These files are executed with
* /bin/sh before starting the shell or command if they exist. They will be
* passed "proto cookie" as arguments if X11 forwarding with spoofing is in
* use. xauth will be run if neither of these exists.
*/
#define SSH_USER_RC ".ssh/rc"
#define SSH_SYSTEM_RC ETCDIR "/sshrc"
/* Ssh-only version of /etc/hosts.equiv. */
/*
* Ssh-only version of /etc/hosts.equiv. Additionally, the daemon may use
* ~/.rhosts and /etc/hosts.equiv if rhosts authentication is enabled.
*/
#define SSH_HOSTS_EQUIV ETCDIR "/shosts.equiv"
/* Additionally, the daemon may use ~/.rhosts and /etc/hosts.equiv if
rhosts authentication is enabled. */
/* Name of the environment variable containing the pathname of the
authentication socket. */
/*
* Name of the environment variable containing the pathname of the
* authentication socket.
*/
#define SSH_AUTHSOCKET_ENV_NAME "SSH_AUTH_SOCK"
/* Name of the environment variable containing the pathname of the
authentication socket. */
/*
* Name of the environment variable containing the pathname of the
* authentication socket.
*/
#define SSH_AGENTPID_ENV_NAME "SSH_AGENT_PID"
/* Force host key length and server key length to differ by at least this
many bits. This is to make double encryption with rsaref work. */
/*
* Force host key length and server key length to differ by at least this
* many bits. This is to make double encryption with rsaref work.
*/
#define SSH_KEY_BITS_RESERVED 128
/* Length of the session key in bytes. (Specified as 256 bits in the
protocol.) */
/*
* Length of the session key in bytes. (Specified as 256 bits in the
* protocol.)
*/
#define SSH_SESSION_KEY_LENGTH 32
/* Name of Kerberos service for SSH to use. */
#define KRB4_SERVICE_NAME "rcmd"
/* Authentication methods. New types can be added, but old types should not
be removed for compatibility. The maximum allowed value is 31. */
/*
* Authentication methods. New types can be added, but old types should not
* be removed for compatibility. The maximum allowed value is 31.
*/
#define SSH_AUTH_RHOSTS 1
#define SSH_AUTH_RSA 2
#define SSH_AUTH_PASSWORD 3
@ -163,20 +195,20 @@ only by root, whereas ssh_config should be world-readable. */
#define SSH_AUTH_TIS 5
#define SSH_AUTH_KERBEROS 6
#define SSH_PASS_KERBEROS_TGT 7
/* 8 to 15 are reserved */
/* 8 to 15 are reserved */
#define SSH_PASS_AFS_TOKEN 21
/* Protocol flags. These are bit masks. */
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes
* screen */
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain
* host */
#define SSH_PROTOFLAG_SCREEN_NUMBER 1 /* X11 forwarding includes screen */
#define SSH_PROTOFLAG_HOST_IN_FWD_OPEN 2 /* forwarding opens contain host */
/* Definition of message types. New values can be added, but old values
should not be removed or without careful consideration of the consequences
for compatibility. The maximum value is 254; value 255 is reserved
for future extension. */
/* Message name *//* msg code *//* arguments */
/*
* Definition of message types. New values can be added, but old values
* should not be removed or without careful consideration of the consequences
* for compatibility. The maximum value is 254; value 255 is reserved for
* future extension.
*/
/* Message name */ /* msg code */ /* arguments */
#define SSH_MSG_NONE 0 /* no message */
#define SSH_MSG_DISCONNECT 1 /* cause (string) */
#define SSH_SMSG_PUBLIC_KEY 2 /* ck,msk,srvk,hostk */
@ -226,45 +258,54 @@ only by root, whereas ssh_config should be world-readable. */
/*------------ definitions for login.c -------------*/
/* Returns the time when the user last logged in. Returns 0 if the
information is not available. This must be called before record_login.
The host from which the user logged in is stored in buf. */
/*
* Returns the time when the user last logged in. Returns 0 if the
* information is not available. This must be called before record_login.
* The host from which the user logged in is stored in buf.
*/
unsigned long
get_last_login_time(uid_t uid, const char *logname,
char *buf, unsigned int bufsize);
/* Records that the user has logged in. This does many things normally
done by login(1). */
/*
* Records that the user has logged in. This does many things normally done
* by login(1).
*/
void
record_login(int pid, const char *ttyname, const char *user, uid_t uid,
const char *host, struct sockaddr_in * addr);
/* Records that the user has logged out. This does many thigs normally
done by login(1) or init. */
/*
* Records that the user has logged out. This does many thigs normally done
* by login(1) or init.
*/
void record_logout(int pid, const char *ttyname);
/*------------ definitions for sshconnect.c ----------*/
/* Opens a TCP/IP connection to the remote server on the given host. If
port is 0, the default port will be used. If anonymous is zero,
a privileged port will be allocated to make the connection.
This requires super-user privileges if anonymous is false.
Connection_attempts specifies the maximum number of tries, one per
second. This returns true on success, and zero on failure. If the
connection is successful, this calls packet_set_connection for the
connection. */
/*
* Opens a TCP/IP connection to the remote server on the given host. If port
* is 0, the default port will be used. If anonymous is zero, a privileged
* port will be allocated to make the connection. This requires super-user
* privileges if anonymous is false. Connection_attempts specifies the
* maximum number of tries, one per second. This returns true on success,
* and zero on failure. If the connection is successful, this calls
* packet_set_connection for the connection.
*/
int
ssh_connect(const char *host, struct sockaddr_in * hostaddr,
int port, int connection_attempts,
int anonymous, uid_t original_real_uid,
const char *proxy_command);
/* Starts a dialog with the server, and authenticates the current user on the
server. This does not need any extra privileges. The basic connection
to the server must already have been established before this is called.
If login fails, this function prints an error and never returns.
This initializes the random state, and leaves it initialized (it will also
have references from the packet module). */
/*
* Starts a dialog with the server, and authenticates the current user on the
* server. This does not need any extra privileges. The basic connection to
* the server must already have been established before this is called. If
* login fails, this function prints an error and never returns. This
* initializes the random state, and leaves it initialized (it will also have
* references from the packet module).
*/
void
ssh_login(int host_key_valid, RSA * host_key, const char *host,
@ -272,41 +313,57 @@ ssh_login(int host_key_valid, RSA * host_key, const char *host,
/*------------ Definitions for various authentication methods. -------*/
/* Tries to authenticate the user using the .rhosts file. Returns true if
authentication succeeds. If ignore_rhosts is non-zero, this will not
consider .rhosts and .shosts (/etc/hosts.equiv will still be used). */
/*
* Tries to authenticate the user using the .rhosts file. Returns true if
* authentication succeeds. If ignore_rhosts is non-zero, this will not
* consider .rhosts and .shosts (/etc/hosts.equiv will still be used).
*/
int auth_rhosts(struct passwd * pw, const char *client_user);
/* Tries to authenticate the user using the .rhosts file and the host using
its host key. Returns true if authentication succeeds. */
/*
* Tries to authenticate the user using the .rhosts file and the host using
* its host key. Returns true if authentication succeeds.
*/
int
auth_rhosts_rsa(struct passwd * pw, const char *client_user,
BIGNUM * client_host_key_e, BIGNUM * client_host_key_n);
/* Tries to authenticate the user using password. Returns true if
authentication succeeds. */
/*
* Tries to authenticate the user using password. Returns true if
* authentication succeeds.
*/
int auth_password(struct passwd * pw, const char *password);
/* Performs the RSA authentication dialog with the client. This returns
0 if the client could not be authenticated, and 1 if authentication was
successful. This may exit if there is a serious protocol violation. */
/*
* Performs the RSA authentication dialog with the client. This returns 0 if
* the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
*/
int auth_rsa(struct passwd * pw, BIGNUM * client_n);
/* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
over the key. Skips any whitespace at the beginning and at end. */
/*
* Parses an RSA key (number of bits, e, n) from a string. Moves the pointer
* over the key. Skips any whitespace at the beginning and at end.
*/
int auth_rsa_read_key(char **cpp, unsigned int *bitsp, BIGNUM * e, BIGNUM * n);
/* Returns the name of the machine at the other end of the socket. The
returned string should be freed by the caller. */
/*
* Returns the name of the machine at the other end of the socket. The
* returned string should be freed by the caller.
*/
char *get_remote_hostname(int socket);
/* Return the canonical name of the host in the other side of the current
connection (as returned by packet_get_connection). The host name is
cached, so it is efficient to call this several times. */
/*
* Return the canonical name of the host in the other side of the current
* connection (as returned by packet_get_connection). The host name is
* cached, so it is efficient to call this several times.
*/
const char *get_canonical_hostname(void);
/* Returns the remote IP address as an ascii string. The value need not be
freed by the caller. */
/*
* Returns the remote IP address as an ascii string. The value need not be
* freed by the caller.
*/
const char *get_remote_ipaddr(void);
/* Returns the port number of the peer of the socket. */
@ -315,16 +372,20 @@ int get_peer_port(int sock);
/* Returns the port number of the remote host. */
int get_remote_port(void);
/* Tries to match the host name (which must be in all lowercase) against the
comma-separated sequence of subpatterns (each possibly preceded by ! to
indicate negation). Returns true if there is a positive match; zero
otherwise. */
/*
* Tries to match the host name (which must be in all lowercase) against the
* comma-separated sequence of subpatterns (each possibly preceded by ! to
* indicate negation). Returns true if there is a positive match; zero
* otherwise.
*/
int match_hostname(const char *host, const char *pattern, unsigned int len);
/* Checks whether the given host is already in the list of our known hosts.
Returns HOST_OK if the host is known and has the specified key,
HOST_NEW if the host is not known, and HOST_CHANGED if the host is known
but used to have a different host key. The host must be in all lowercase. */
/*
* Checks whether the given host is already in the list of our known hosts.
* Returns HOST_OK if the host is known and has the specified key, HOST_NEW
* if the host is not known, and HOST_CHANGED if the host is known but used
* to have a different host key. The host must be in all lowercase.
*/
typedef enum {
HOST_OK, HOST_NEW, HOST_CHANGED
} HostStatus;
@ -332,43 +393,55 @@ HostStatus
check_host_in_hostfile(const char *filename, const char *host,
BIGNUM * e, BIGNUM * n, BIGNUM * ke, BIGNUM * kn);
/* Appends an entry to the host file. Returns false if the entry
could not be appended. */
/*
* Appends an entry to the host file. Returns false if the entry could not
* be appended.
*/
int
add_host_to_hostfile(const char *filename, const char *host,
BIGNUM * e, BIGNUM * n);
/* Performs the RSA authentication challenge-response dialog with the client,
and returns true (non-zero) if the client gave the correct answer to
our challenge; returns zero if the client gives a wrong answer. */
/*
* Performs the RSA authentication challenge-response dialog with the client,
* and returns true (non-zero) if the client gave the correct answer to our
* challenge; returns zero if the client gives a wrong answer.
*/
int auth_rsa_challenge_dialog(BIGNUM * e, BIGNUM * n);
/* Reads a passphrase from /dev/tty with echo turned off. Returns the
passphrase (allocated with xmalloc). Exits if EOF is encountered.
If from_stdin is true, the passphrase will be read from stdin instead. */
/*
* Reads a passphrase from /dev/tty with echo turned off. Returns the
* passphrase (allocated with xmalloc). Exits if EOF is encountered. If
* from_stdin is true, the passphrase will be read from stdin instead.
*/
char *read_passphrase(const char *prompt, int from_stdin);
/* Saves the authentication (private) key in a file, encrypting it with
passphrase. The identification of the file (lowest 64 bits of n)
will precede the key to provide identification of the key without
needing a passphrase. */
/*
* Saves the authentication (private) key in a file, encrypting it with
* passphrase. The identification of the file (lowest 64 bits of n) will
* precede the key to provide identification of the key without needing a
* passphrase.
*/
int
save_private_key(const char *filename, const char *passphrase,
RSA * private_key, const char *comment);
/* Loads the public part of the key file (public key and comment).
Returns 0 if an error occurred; zero if the public key was successfully
read. The comment of the key is returned in comment_return if it is
non-NULL; the caller must free the value with xfree. */
/*
* Loads the public part of the key file (public key and comment). Returns 0
* if an error occurred; zero if the public key was successfully read. The
* comment of the key is returned in comment_return if it is non-NULL; the
* caller must free the value with xfree.
*/
int
load_public_key(const char *filename, RSA * pub,
char **comment_return);
/* Loads the private key from the file. Returns 0 if an error is encountered
(file does not exist or is not readable, or passphrase is bad).
This initializes the private key. The comment of the key is returned
in comment_return if it is non-NULL; the caller must free the value
with xfree. */
/*
* Loads the private key from the file. Returns 0 if an error is encountered
* (file does not exist or is not readable, or passphrase is bad). This
* initializes the private key. The comment of the key is returned in
* comment_return if it is non-NULL; the caller must free the value with
* xfree.
*/
int
load_private_key(const char *filename, const char *passphrase,
RSA * private_key, char **comment_return);
@ -418,9 +491,11 @@ void debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
/* same as fatal() but w/o logging */
void fatal_cleanup(void);
/* Registers a cleanup function to be called by fatal()/fatal_cleanup() before exiting.
It is permissible to call fatal_remove_cleanup for the function itself
from the function. */
/*
* Registers a cleanup function to be called by fatal()/fatal_cleanup()
* before exiting. It is permissible to call fatal_remove_cleanup for the
* function itself from the function.
*/
void fatal_add_cleanup(void (*proc) (void *context), void *context);
/* Removes a cleanup function to be called at fatal(). */
@ -431,9 +506,11 @@ void fatal_remove_cleanup(void (*proc) (void *context), void *context);
/* 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. */
/*
* 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. */
@ -442,16 +519,20 @@ 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. */
/*
* 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. */
/*
* 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. */
@ -473,8 +554,10 @@ void channel_input_open_failure(void);
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. */
/*
* 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. */
@ -483,92 +566,123 @@ 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. */
/*
* 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. */
/*
* 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(int port, const char *host,
int remote_port);
/* 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. */
/*
* 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(int port, const char *host,
int 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. */
/*
* 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. */
/*
* 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. */
/*
* 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. */
/*
* 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. */
/*
* 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);
/* 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. */
/*
* 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. */
/*
* 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. */
/*
* 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. */
/*
* 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. */
/*
* 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. */
/*
* Returns true if the given string matches the pattern (which may contain ?
* and * as wildcards), and zero if it does not match.
*/
int match_pattern(const char *s, const char *pattern);
/* Expands tildes in the file name. Returns data allocated by xmalloc.
Warning: this calls getpw*. */
/*
* Expands tildes in the file name. Returns data allocated by xmalloc.
* Warning: this calls getpw*.
*/
char *tilde_expand_filename(const char *filename, uid_t my_uid);
/* Performs the interactive session. This handles data transmission between
the client and the program. Note that the notion of stdin, stdout, and
stderr in this function is sort of reversed: this function writes to
stdin (of the child program), and reads from stdout and stderr (of the
child program). */
/*
* Performs the interactive session. This handles data transmission between
* the client and the program. Note that the notion of stdin, stdout, and
* stderr in this function is sort of reversed: this function writes to stdin
* (of the child program), and reads from stdout and stderr (of the child
* program).
*/
void server_loop(int pid, int fdin, int fdout, int fderr);
/* Client side main loop for the interactive session. */
@ -582,9 +696,11 @@ struct envstring {
#ifdef KRB4
#include <krb.h>
/* Performs Kerberos v4 mutual authentication with the client. This returns
0 if the client could not be authenticated, and 1 if authentication was
successful. This may exit if there is a serious protocol violation. */
/*
* Performs Kerberos v4 mutual authentication with the client. This returns 0
* if the client could not be authenticated, and 1 if authentication was
* successful. This may exit if there is a serious protocol violation.
*/
int auth_krb4(const char *server_user, KTEXT auth, char **client);
int krb4_init(uid_t uid);
void krb4_cleanup_proc(void *ignore);

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

@ -8,7 +8,7 @@
*/
#include "includes.h"
RCSID("$Id: sshconnect.c,v 1.14 1999/11/24 13:26:23 damien Exp $");
RCSID("$Id: sshconnect.c,v 1.15 1999/11/25 00:54:59 damien Exp $");
#ifdef HAVE_OPENSSL
#include <openssl/bn.h>
@ -142,8 +142,10 @@ ssh_create_socket(uid_t original_real_uid, int privileged)
{
int sock;
/* If we are running as root and want to connect to a privileged
port, bind our own socket to a privileged port. */
/*
* If we are running as root and want to connect to a privileged
* port, bind our own socket to a privileged port.
*/
if (privileged) {
int p = IPPORT_RESERVED - 1;
@ -227,9 +229,11 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
!anonymous && geteuid() == 0 &&
port < IPPORT_RESERVED);
/* Connect to the host. We use the user's uid in
the hope that it will help with the problems of
tcp_wrappers showing the remote uid as root. */
/*
* Connect to the host. We use the user's uid in the
* hope that it will help with the problems of
* tcp_wrappers showing the remote uid as root.
*/
temporarily_use_uid(original_real_uid);
if (connect(sock, (struct sockaddr *) hostaddr, sizeof(*hostaddr))
>= 0) {
@ -270,8 +274,12 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
!anonymous && geteuid() == 0 &&
port < IPPORT_RESERVED);
/* Connect to the host. We use the user's uid in the hope that
it will help with tcp_wrappers showing the remote uid as root. */
/*
* Connect to the host. We use the user's
* uid in the hope that it will help with
* tcp_wrappers showing the remote uid as
* root.
*/
temporarily_use_uid(original_real_uid);
if (connect(sock, (struct sockaddr *) hostaddr,
sizeof(*hostaddr)) >= 0) {
@ -282,8 +290,12 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
debug("connect: %.100s", strerror(errno));
restore_uid();
/* Close the failed socket; there appear to be some problems when
reusing a socket for which connect() has already returned an error. */
/*
* Close the failed socket; there appear to
* be some problems when reusing a socket for
* which connect() has already returned an
* error.
*/
shutdown(sock, SHUT_RDWR);
close(sock);
}
@ -300,10 +312,11 @@ ssh_connect(const char *host, struct sockaddr_in * hostaddr,
debug("Connection established.");
/* Set socket options. We would like the socket to disappear as
soon as it has been closed for whatever reason. */
/* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
sizeof(on)); */
/*
* Set socket options. We would like the socket to disappear as soon
* as it has been closed for whatever reason.
*/
/* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &on, sizeof(on));
linger.l_onoff = 1;
linger.l_linger = 5;
@ -493,8 +506,10 @@ try_rsa_authentication(struct passwd * pw, const char *authfile)
/* Wait for server's response. */
type = packet_read(&plen);
/* The server responds with failure if it doesn\'t like our key or
doesn\'t support RSA authentication. */
/*
* The server responds with failure if it doesn\'t like our key or
* doesn\'t support RSA authentication.
*/
if (type == SSH_SMSG_FAILURE) {
debug("Server refused our key.");
xfree(comment);
@ -514,8 +529,10 @@ try_rsa_authentication(struct passwd * pw, const char *authfile)
debug("Received RSA challenge from server.");
private_key = RSA_new();
/* Load the private key. Try first with empty passphrase; if it
fails, ask for a passphrase. */
/*
* Load the private key. Try first with empty passphrase; if it
* fails, ask for a passphrase.
*/
if (!load_private_key(authfile, "", private_key, NULL)) {
char buf[300];
snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
@ -720,9 +737,11 @@ try_kerberos_authentication()
packet_integrity_check(plen, 4 + auth.length, type);
/* If his response isn't properly encrypted with the
session key, and the decrypted checksum fails to match,
he's bogus. Bail out. */
/*
* If his response isn't properly encrypted with the session
* key, and the decrypted checksum fails to match, he's
* bogus. Bail out.
*/
r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
&foreign, &local, &msg_data);
if (r != KSUCCESS) {
@ -894,8 +913,10 @@ ssh_exchange_identification()
}
buf[sizeof(buf) - 1] = 0;
/* Check that the versions match. In future this might accept
several versions and set appropriate flags to handle them. */
/*
* Check that the versions match. In future this might accept
* several versions and set appropriate flags to handle them.
*/
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
remote_version) != 3)
fatal("Bad remote protocol version identification: '%.100s'", buf);
@ -916,9 +937,11 @@ ssh_exchange_identification()
}
}
#if 0
/* Removed for now, to permit compatibility with latter versions.
The server will reject our version and disconnect if it doesn't
support it. */
/*
* Removed for now, to permit compatibility with latter versions. The
* server will reject our version and disconnect if it doesn't
* support it.
*/
if (remote_major != PROTOCOL_MAJOR)
fatal("Protocol major versions differ: %d vs. %d",
PROTOCOL_MAJOR, remote_major);
@ -1086,10 +1109,7 @@ ssh_login(int host_key_valid,
protocol_flags = packet_get_int();
packet_set_protocol_flags(protocol_flags);
/* Get supported cipher types. */
supported_ciphers = packet_get_int();
/* Get supported authentication types. */
supported_authentications = packet_get_int();
debug("Received server public key (%d bits) and host key (%d bits).",
@ -1099,11 +1119,12 @@ ssh_login(int host_key_valid,
8 + 4 + sum_len + 0 + 4 + 0 + 0 + 4 + 4 + 4,
SSH_SMSG_PUBLIC_KEY);
/* Compute the session id. */
compute_session_id(session_id, check_bytes, host_key->n, public_key->n);
/* Check if the host key is present in the user\'s list of known
hosts or in the systemwide list. */
/*
* Check if the host key is present in the user\'s list of known
* hosts or in the systemwide list.
*/
host_status = check_host_in_hostfile(options.user_hostfile, host,
host_key->e, host_key->n,
file_key->e, file_key->n);
@ -1111,18 +1132,22 @@ ssh_login(int host_key_valid,
host_status = check_host_in_hostfile(options.system_hostfile, host,
host_key->e, host_key->n,
file_key->e, file_key->n);
/* Force accepting of the host key for localhost and 127.0.0.1.
The problem is that if the home directory is NFS-mounted to
multiple machines, localhost will refer to a different machine
in each of them, and the user will get bogus HOST_CHANGED
warnings. This essentially disables host authentication for
localhost; however, this is probably not a real problem. */
/*
* Force accepting of the host key for localhost and 127.0.0.1. The
* problem is that if the home directory is NFS-mounted to multiple
* machines, localhost will refer to a different machine in each of
* them, and the user will get bogus HOST_CHANGED warnings. This
* essentially disables host authentication for localhost; however,
* this is probably not a real problem.
*/
if (local) {
debug("Forcing accepting of host key for localhost.");
host_status = HOST_OK;
}
/* Also perform check for the ip address, skip the check if we are
localhost or the hostname was an ip address to begin with */
/*
* Also perform check for the ip address, skip the check if we are
* localhost or the hostname was an ip address to begin with
*/
if (options.check_host_ip && !local && strcmp(host, ip)) {
RSA *ip_key = RSA_new();
ip_key->n = BN_new();
@ -1226,13 +1251,18 @@ ssh_login(int host_key_valid,
error("Add correct host key in %.100s to get rid of this message.",
options.user_hostfile);
/* If strict host key checking is in use, the user will
have to edit the key manually and we can only abort. */
/*
* If strict host key checking is in use, the user will have
* to edit the key manually and we can only abort.
*/
if (options.strict_host_key_checking)
fatal("Host key for %.200s has changed and you have requested strict checking.", host);
/* If strict host key checking has not been requested, allow the connection
but without password authentication or agent forwarding. */
/*
* If strict host key checking has not been requested, allow
* the connection but without password authentication or
* agent forwarding.
*/
if (options.password_authentication) {
error("Password authentication is disabled to avoid trojan horses.");
options.password_authentication = 0;
@ -1241,11 +1271,13 @@ ssh_login(int host_key_valid,
error("Agent forwarding is disabled to avoid trojan horses.");
options.forward_agent = 0;
}
/* XXX Should permit the user to change to use the new id.
This could be done by converting the host key to an
identifying sentence, tell that the host identifies
itself by that sentence, and ask the user if he/she
whishes to accept the authentication. */
/*
* XXX Should permit the user to change to use the new id.
* This could be done by converting the host key to an
* identifying sentence, tell that the host identifies itself
* by that sentence, and ask the user if he/she whishes to
* accept the authentication.
*/
break;
}
@ -1255,9 +1287,11 @@ ssh_login(int host_key_valid,
/* Generate a session key. */
arc4random_stir();
/* Generate an encryption key for the session. The key is a 256
bit random number, interpreted as a 32-byte key, with the least
significant 8 bits being the first byte of the key. */
/*
* Generate an encryption key for the session. The key is a 256 bit
* random number, interpreted as a 32-byte key, with the least
* significant 8 bits being the first byte of the key.
*/
for (i = 0; i < 32; i++) {
if (i % 4 == 0)
rand = arc4random();
@ -1265,9 +1299,11 @@ ssh_login(int host_key_valid,
rand >>= 8;
}
/* According to the protocol spec, the first byte of the session
key is the highest byte of the integer. The session key is
xored with the first 16 bytes of the session id. */
/*
* According to the protocol spec, the first byte of the session key
* is the highest byte of the integer. The session key is xored with
* the first 16 bytes of the session id.
*/
key = BN_new();
BN_set_word(key, 0);
for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {
@ -1278,8 +1314,10 @@ ssh_login(int host_key_valid,
BN_add_word(key, session_key[i]);
}
/* Encrypt the integer using the public key and host key of the
server (key with smaller modulus first). */
/*
* Encrypt the integer using the public key and host key of the
* server (key with smaller modulus first).
*/
if (BN_cmp(public_key->n, host_key->n) < 0) {
/* Public key has smaller modulus. */
if (BN_num_bits(host_key->n) <
@ -1354,8 +1392,10 @@ ssh_login(int host_key_valid,
/* We will no longer need the session key here. Destroy any extra copies. */
memset(session_key, 0, sizeof(session_key));
/* Expect a success message from the server. Note that this
message will be received in encrypted form. */
/*
* Expect a success message from the server. Note that this message
* will be received in encrypted form.
*/
packet_read_expect(&payload_len, SSH_SMSG_SUCCESS);
debug("Received encrypted confirmation.");
@ -1366,9 +1406,11 @@ ssh_login(int host_key_valid,
packet_send();
packet_write_wait();
/* The server should respond with success if no authentication is
needed (the user has no password). Otherwise the server
responds with failure. */
/*
* The server should respond with success if no authentication is
* needed (the user has no password). Otherwise the server responds
* with failure.
*/
type = packet_read(&payload_len);
/* check whether the connection was accepted without authentication. */
@ -1410,8 +1452,10 @@ ssh_login(int host_key_valid,
}
#endif /* KRB4 */
/* Use rhosts authentication if running in privileged socket and
we do not wish to remain anonymous. */
/*
* Use rhosts authentication if running in privileged socket and we
* do not wish to remain anonymous.
*/
if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) &&
options.rhosts_authentication) {
debug("Trying rhosts authentication.");
@ -1428,8 +1472,10 @@ ssh_login(int host_key_valid,
packet_disconnect("Protocol error: got %d in response to rhosts auth",
type);
}
/* Try .rhosts or /etc/hosts.equiv authentication with RSA host
authentication. */
/*
* Try .rhosts or /etc/hosts.equiv authentication with RSA host
* authentication.
*/
if ((supported_authentications & (1 << SSH_AUTH_RHOSTS_RSA)) &&
options.rhosts_rsa_authentication && host_key_valid) {
if (try_rhosts_rsa_authentication(local_user, own_host_key))
@ -1438,10 +1484,11 @@ ssh_login(int host_key_valid,
/* Try RSA authentication if the server supports it. */
if ((supported_authentications & (1 << SSH_AUTH_RSA)) &&
options.rsa_authentication) {
/* Try RSA authentication using the authentication agent.
The agent is tried first because no passphrase is
needed for it, whereas identity files may require
passphrases. */
/*
* Try RSA authentication using the authentication agent. The
* agent is tried first because no passphrase is needed for
* it, whereas identity files may require passphrases.
*/
if (try_agent_authentication())
return;

499
sshd.c
Просмотреть файл

@ -11,7 +11,7 @@
*/
#include "includes.h"
RCSID("$Id: sshd.c,v 1.31 1999/11/24 23:42:08 damien Exp $");
RCSID("$Id: sshd.c,v 1.32 1999/11/25 00:54:59 damien Exp $");
#include "xmalloc.h"
#include "rsa.h"
@ -65,12 +65,16 @@ char *av0;
/* Saved arguments to main(). */
char **saved_argv;
/* This is set to the socket that the server is listening; this is used in
the SIGHUP signal handler. */
/*
* This is set to the socket that the server is listening; this is used in
* the SIGHUP signal handler.
*/
int listen_sock;
/* the client's version string, passed by sshd2 in compat mode.
if != NULL, sshd will skip the version-number exchange */
/*
* the client's version string, passed by sshd2 in compat mode. if != NULL,
* sshd will skip the version-number exchange
*/
char *client_version_string = NULL;
/* Flags set in auth-rsa from authorized_keys flags. These are set in auth-rsa.c. */
@ -88,19 +92,23 @@ struct envstring *custom_environment = NULL;
/* Session id for the current session. */
unsigned char session_id[16];
/* Any really sensitive data in the application is contained in this structure.
The idea is that this structure could be locked into memory so that the
pages do not get written into swap. However, there are some problems.
The private key contains BIGNUMs, and we do not (in principle) have
access to the internals of them, and locking just the structure is not
very useful. Currently, memory locking is not implemented. */
/*
* Any really sensitive data in the application is contained in this
* structure. The idea is that this structure could be locked into memory so
* that the pages do not get written into swap. However, there are some
* problems. The private key contains BIGNUMs, and we do not (in principle)
* have access to the internals of them, and locking just the structure is
* not very useful. Currently, memory locking is not implemented.
*/
struct {
RSA *private_key; /* Private part of server key. */
RSA *host_key; /* Private part of host key. */
} sensitive_data;
/* Flag indicating whether the current session key has been used. This flag
is set whenever the key is used, and cleared when the key is regenerated. */
/*
* Flag indicating whether the current session key has been used. This flag
* is set whenever the key is used, and cleared when the key is regenerated.
*/
int key_used = 0;
/* This is set to true when SIGHUP is received. */
@ -466,7 +474,7 @@ main(int ac, char **av)
fprintf(stderr, "sshd version %s\n", SSH_VERSION);
fprintf(stderr, "Usage: %s [options]\n", av0);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -f file Configuration file (default %s/sshd_config)\n", ETCDIR);
fprintf(stderr, " -f file Configuration file (default %s)\n", SERVER_CONFIG_FILE);
fprintf(stderr, " -d Debugging mode\n");
fprintf(stderr, " -i Started from inetd\n");
fprintf(stderr, " -q Quiet (no logging)\n");
@ -614,13 +622,11 @@ main(int ac, char **av)
setsockopt(listen_sock, SOL_SOCKET, SO_LINGER, (void *) &linger,
sizeof(linger));
/* Initialize the socket address. */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr = options.listen_addr;
sin.sin_port = htons(options.port);
/* Bind the socket to the desired port. */
if (bind(listen_sock, (struct sockaddr *) & sin, sizeof(sin)) < 0) {
error("bind: %.100s", strerror(errno));
shutdown(listen_sock, SHUT_RDWR);
@ -628,12 +634,13 @@ main(int ac, char **av)
fatal("Bind to port %d failed.", options.port);
}
if (!debug_flag) {
/* Record our pid in /etc/sshd_pid to make it
easier to kill the correct sshd. We don\'t
want to do this before the bind above because
the bind will fail if there already is a
daemon, and this will overwrite any old pid in
the file. */
/*
* Record our pid in /etc/sshd_pid to make it easier
* to kill the correct sshd. We don\'t want to do
* this before the bind above because the bind will
* fail if there already is a daemon, and this will
* overwrite any old pid in the file.
*/
f = fopen(SSH_DAEMON_PID_FILE, "w");
if (f) {
fprintf(f, "%u\n", (unsigned int) getpid());
@ -666,8 +673,10 @@ main(int ac, char **av)
/* Arrange SIGCHLD to be caught. */
signal(SIGCHLD, main_sigchld_handler);
/* Stay listening for connections until the system crashes
or the daemon is killed with a signal. */
/*
* Stay listening for connections until the system crashes or
* the daemon is killed with a signal.
*/
for (;;) {
if (received_sighup)
sighup_restart();
@ -682,12 +691,16 @@ main(int ac, char **av)
error("accept: %.100s", strerror(errno));
continue;
}
/* Got connection. Fork a child to handle it,
unless we are in debugging mode. */
/*
* Got connection. Fork a child to handle it, unless
* we are in debugging mode.
*/
if (debug_flag) {
/* In debugging mode. Close the listening
socket, and start processing the
connection without forking. */
/*
* In debugging mode. Close the listening
* socket, and start processing the
* connection without forking.
*/
debug("Server will not fork when running in debugging mode.");
close(listen_sock);
sock_in = newsock;
@ -695,16 +708,17 @@ main(int ac, char **av)
pid = getpid();
break;
} else {
/* Normal production daemon. Fork, and
have the child process the connection.
The parent continues listening. */
/*
* Normal production daemon. Fork, and have
* the child process the connection. The
* parent continues listening.
*/
if ((pid = fork()) == 0) {
/* Child. Close the listening
socket, and start using the
accepted socket. Reinitialize
logging (since our pid has
changed). We break out of the
loop to handle the connection. */
/*
* Child. Close the listening socket, and start using the
* accepted socket. Reinitialize logging (since our pid has
* changed). We break out of the loop to handle the connection.
*/
close(listen_sock);
sock_in = newsock;
sock_out = newsock;
@ -731,9 +745,11 @@ main(int ac, char **av)
/* This is the child processing a new connection. */
/* Disable the key regeneration alarm. We will not regenerate the
key since we are no longer in a position to give it to anyone.
We will not restart on SIGHUP since it no longer makes sense. */
/*
* Disable the key regeneration alarm. We will not regenerate the
* key since we are no longer in a position to give it to anyone. We
* will not restart on SIGHUP since it no longer makes sense.
*/
alarm(0);
signal(SIGALRM, SIG_DFL);
signal(SIGHUP, SIG_DFL);
@ -741,17 +757,20 @@ main(int ac, char **av)
signal(SIGQUIT, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
/* Set socket options for the connection. We want the socket to
close as fast as possible without waiting for anything. If the
connection is not a socket, these will do nothing. */
/* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
sizeof(on)); */
/*
* Set socket options for the connection. We want the socket to
* close as fast as possible without waiting for anything. If the
* connection is not a socket, these will do nothing.
*/
/* setsockopt(sock_in, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
linger.l_onoff = 1;
linger.l_linger = 5;
setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));
/* Register our connection. This turns encryption off because we
do not have a key. */
/*
* Register our connection. This turns encryption off because we do
* not have a key.
*/
packet_set_connection(sock_in, sock_out);
remote_port = get_remote_port();
@ -777,12 +796,14 @@ main(int ac, char **av)
verbose("Connection from %.500s port %d", remote_ip, remote_port);
#endif /* LIBWRAP */
/* We don\'t want to listen forever unless the other side
successfully authenticates itself. So we set up an alarm which
is cleared after successful authentication. A limit of zero
indicates no limit. Note that we don\'t set the alarm in
debugging mode; it is just annoying to have the server exit
just when you are about to discover the bug. */
/*
* We don\'t want to listen forever unless the other side
* successfully authenticates itself. So we set up an alarm which is
* cleared after successful authentication. A limit of zero
* indicates no limit. Note that we don\'t set the alarm in debugging
* mode; it is just annoying to have the server exit just when you
* are about to discover the bug.
*/
signal(SIGALRM, grace_alarm_handler);
if (!debug_flag)
alarm(options.login_grace_time);
@ -815,8 +836,10 @@ main(int ac, char **av)
buf[sizeof(buf) - 1] = 0;
}
/* Check that the versions match. In future this might accept
several versions and set appropriate flags to handle them. */
/*
* Check that the versions match. In future this might accept
* several versions and set appropriate flags to handle them.
*/
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", &remote_major, &remote_minor,
remote_version) != 3) {
const char *s = "Protocol mismatch.\n";
@ -848,11 +871,13 @@ main(int ac, char **av)
no_agent_forwarding_flag = 1;
}
}
/* Check that the connection comes from a privileged port. Rhosts-
and Rhosts-RSA-Authentication only make sense from priviledged
programs. Of course, if the intruder has root access on his
local machine, he can connect from any port. So do not use
these authentication methods from machines that you do not trust. */
/*
* Check that the connection comes from a privileged port. Rhosts-
* and Rhosts-RSA-Authentication only make sense from priviledged
* programs. Of course, if the intruder has root access on his local
* machine, he can connect from any port. So do not use these
* authentication methods from machines that you do not trust.
*/
if (remote_port >= IPPORT_RESERVED ||
remote_port < IPPORT_RESERVED / 2) {
options.rhosts_authentication = 0;
@ -914,13 +939,15 @@ do_connection()
int plen, slen;
u_int32_t rand = 0;
/* Generate check bytes that the client must send back in the user
packet in order for it to be accepted; this is used to defy ip
spoofing attacks. Note that this only works against somebody
doing IP spoofing from a remote machine; any machine on the
local network can still see outgoing packets and catch the
random cookie. This only affects rhosts authentication, and
this is one of the reasons why it is inherently insecure. */
/*
* Generate check bytes that the client must send back in the user
* packet in order for it to be accepted; this is used to defy ip
* spoofing attacks. Note that this only works against somebody
* doing IP spoofing from a remote machine; any machine on the local
* network can still see outgoing packets and catch the random
* cookie. This only affects rhosts authentication, and this is one
* of the reasons why it is inherently insecure.
*/
for (i = 0; i < 8; i++) {
if (i % 4 == 0)
rand = arc4random();
@ -928,9 +955,11 @@ do_connection()
rand >>= 8;
}
/* Send our public key. We include in the packet 64 bits of
random data that must be matched in the reply in order to
prevent IP spoofing. */
/*
* Send our public key. We include in the packet 64 bits of random
* data that must be matched in the reply in order to prevent IP
* spoofing.
*/
packet_start(SSH_SMSG_PUBLIC_KEY);
for (i = 0; i < 8; i++)
packet_put_char(check_bytes[i]);
@ -1002,14 +1031,15 @@ do_connection()
session_key_int = BN_new();
packet_get_bignum(session_key_int, &slen);
/* Get protocol flags. */
protocol_flags = packet_get_int();
packet_set_protocol_flags(protocol_flags);
packet_integrity_check(plen, 1 + 8 + slen + 4, SSH_CMSG_SESSION_KEY);
/* Decrypt it using our private server key and private host key
(key with larger modulus first). */
/*
* Decrypt it using our private server key and private host key (key
* with larger modulus first).
*/
if (BN_cmp(sensitive_data.private_key->n, sensitive_data.host_key->n) > 0) {
/* Private key has bigger modulus. */
if (BN_num_bits(sensitive_data.private_key->n) <
@ -1040,14 +1070,15 @@ do_connection()
sensitive_data.private_key);
}
/* Compute session id for this session. */
compute_session_id(session_id, check_bytes,
sensitive_data.host_key->n,
sensitive_data.private_key->n);
/* Extract session key from the decrypted integer. The key is in
the least significant 256 bits of the integer; the first byte
of the key is in the highest bits. */
/*
* Extract session key from the decrypted integer. The key is in the
* least significant 256 bits of the integer; the first byte of the
* key is in the highest bits.
*/
BN_mask_bits(session_key_int, sizeof(session_key) * 8);
len = BN_num_bytes(session_key_int);
if (len < 0 || len > sizeof(session_key))
@ -1125,8 +1156,7 @@ allowed_user(struct passwd * pw)
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 */
/* 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;
@ -1151,8 +1181,10 @@ allowed_user(struct passwd * pw)
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 */
/*
* 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;
@ -1216,8 +1248,10 @@ do_authentication(char *user)
}
#endif
/* If we are not running as root, the user must have the same uid
as the server. */
/*
* 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.");
@ -1357,10 +1391,12 @@ do_authloop(struct passwd * pw)
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.) */
/*
* 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);
@ -1379,9 +1415,11 @@ do_authloop(struct passwd * pw)
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. */
/*
* 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. */
@ -1425,9 +1463,11 @@ do_authloop(struct passwd * pw)
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. */
/*
* 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);
@ -1463,8 +1503,7 @@ do_authloop(struct passwd * pw)
skeyinfo = skey_fake_keyinfo(pw->pw_name);
}
if (skeyinfo != NULL) {
/* we send our s/key- in
tis-challenge messages */
/* 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));
@ -1493,8 +1532,10 @@ do_authloop(struct passwd * pw)
#endif
default:
/* Any unknown messages will be ignored (and
failure returned) during authentication. */
/*
* Any unknown messages will be ignored (and failure
* returned) during authentication.
*/
log("Unknown message during authentication: type %d", type);
break;
}
@ -1559,11 +1600,12 @@ do_fake_authloop(char *user)
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. */
/*
* 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. */
/* Read a packet. This will not return if the client disconnects. */
int plen;
int type = packet_read(&plen);
#ifdef SKEY
@ -1583,8 +1625,10 @@ do_fake_authloop(char *user)
if (attempt > AUTH_FAIL_MAX)
packet_disconnect(AUTH_FAIL_MSG, user);
/* Send failure. This should be indistinguishable from a
failed authentication. */
/*
* Send failure. This should be indistinguishable from a
* failed authentication.
*/
packet_start(SSH_SMSG_FAILURE);
packet_send();
packet_write_wait();
@ -1630,19 +1674,25 @@ do_authenticated(struct passwd * pw)
mode_t tty_mode;
int n_bytes;
/* Cancel the alarm we set to limit the time taken for
authentication. */
/*
* Cancel the alarm we set to limit the time taken for
* authentication.
*/
alarm(0);
/* Inform the channel mechanism that we are the server side and
that the client may request to connect to any port at all.
(The user could do it anyway, and we wouldn\'t know what is
permitted except by the client telling us, so we can equally
well trust the client not to request anything bogus.) */
/*
* Inform the channel mechanism that we are the server side and that
* the client may request to connect to any port at all. (The user
* could do it anyway, and we wouldn\'t know what is permitted except
* by the client telling us, so we can equally well trust the client
* not to request anything bogus.)
*/
channel_permit_all_opens();
/* We stay in this loop until the client requests to execute a
shell or a command. */
/*
* We stay in this loop until the client requests to execute a shell
* or a command.
*/
while (1) {
int plen, dlen;
@ -1826,8 +1876,10 @@ do_authenticated(struct passwd * pw)
return;
default:
/* Any unknown messages in this phase are ignored,
and a failure message is returned. */
/*
* Any unknown messages in this phase are ignored,
* and a failure message is returned.
*/
log("Unknown packet type received after authentication: %d", type);
goto fail;
}
@ -1852,8 +1904,10 @@ fail:
continue;
do_forced_command:
/* There is a forced command specified for this login.
Execute it. */
/*
* There is a forced command specified for this login.
* Execute it.
*/
debug("Executing forced command: %.900s", forced_command);
if (have_pty)
do_exec_pty(forced_command, ptyfd, ttyfd, ttyname, pw, term, display, proto, data);
@ -1897,14 +1951,18 @@ do_exec_no_pty(const char *command, struct passwd * pw,
/* Child. Reinitialize the log since the pid has changed. */
log_init(av0, options.log_level, options.log_facility, log_stderr);
/* Create a new session and process group since the 4.4BSD
setlogin() affects the entire process group. */
/*
* Create a new session and process group since the 4.4BSD
* setlogin() affects the entire process group.
*/
if (setsid() < 0)
error("setsid failed: %.100s", strerror(errno));
#ifdef USE_PIPES
/* Redirect stdin. We close the parent side of the socket
pair, and make the child side the standard input. */
/*
* Redirect stdin. We close the parent side of the socket
* pair, and make the child side the standard input.
*/
close(pin[1]);
if (dup2(pin[0], 0) < 0)
perror("dup2 stdin");
@ -1922,9 +1980,11 @@ do_exec_no_pty(const char *command, struct passwd * pw,
perror("dup2 stderr");
close(perr[1]);
#else /* USE_PIPES */
/* Redirect stdin, stdout, and stderr. Stdin and stdout
will use the same socket, as some programs
(particularly rdist) seem to depend on it. */
/*
* Redirect stdin, stdout, and stderr. Stdin and stdout will
* use the same socket, as some programs (particularly rdist)
* seem to depend on it.
*/
close(inout[1]);
close(err[1]);
if (dup2(inout[0], 0) < 0) /* stdin */
@ -1955,8 +2015,10 @@ do_exec_no_pty(const char *command, struct passwd * pw,
close(inout[0]);
close(err[0]);
/* Enter the interactive session. Note: server_loop must be able
to handle the case that fdin and fdout are the same. */
/*
* Enter the interactive session. Note: server_loop must be able to
* handle the case that fdin and fdout are the same.
*/
server_loop(pid, inout[1], inout[1], err[1]);
/* server_loop has closed inout[1] and err[1]. */
#endif /* USE_PIPES */
@ -2012,8 +2074,10 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
/* Get remote host name. */
hostname = get_canonical_hostname();
/* Get the time when the user last logged in. Buf will be set to
contain the hostname the last login was from. */
/*
* Get the time when the user last logged in. Buf will be set to
* contain the hostname the last login was from.
*/
if (!options.use_login) {
last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name,
buf, sizeof(buf));
@ -2049,9 +2113,11 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
/* Close the extra descriptor for the pseudo tty. */
close(ttyfd);
/* Get IP address of client. This is needed because we
want to record where the user logged in from. If the
connection is not a socket, let the ip address be 0.0.0.0. */
/*
* Get IP address of client. This is needed because we want
* to record where the user logged in from. If the
* connection is not a socket, let the ip address be 0.0.0.0.
*/
memset(&from, 0, sizeof(from));
if (packet_get_connection_in() == packet_get_connection_out()) {
fromlen = sizeof(from);
@ -2075,12 +2141,14 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
fprintf(stderr, pamconv_msg);
#endif
/* If the user has logged in before, display the time of
last login. However, don't display anything extra if a
command has been specified (so that ssh can be used to
execute commands on a remote machine without users
knowing they are going to another machine). Login(1)
will do this for us as well, so check if login(1) is used */
/*
* If the user has logged in before, display the time of last
* login. However, don't display anything extra if a command
* has been specified (so that ssh can be used to execute
* commands on a remote machine without users knowing they
* are going to another machine). Login(1) will do this for
* us as well, so check if login(1) is used
*/
if (command == NULL && last_login_time != 0 && !quiet_login &&
!options.use_login) {
/* Convert the date to a string. */
@ -2095,10 +2163,12 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
else
printf("Last login: %s from %s\r\n", time_string, buf);
}
/* Print /etc/motd unless a command was specified or
printing it was disabled in server options or login(1)
will be used. Note that some machines appear to print
it in /etc/profile or similar. */
/*
* Print /etc/motd unless a command was specified or printing
* it was disabled in server options or login(1) will be
* used. Note that some machines appear to print it in
* /etc/profile or similar.
*/
if (command == NULL && options.print_motd && !quiet_login &&
!options.use_login) {
/* Print /etc/motd if it exists. */
@ -2118,15 +2188,19 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
/* Parent. Close the slave side of the pseudo tty. */
close(ttyfd);
/* Create another descriptor of the pty master side for use as the
standard input. We could use the original descriptor, but this
simplifies code in server_loop. The descriptor is bidirectional. */
/*
* Create another descriptor of the pty master side for use as the
* standard input. We could use the original descriptor, but this
* simplifies code in server_loop. The descriptor is bidirectional.
*/
fdout = dup(ptyfd);
if (fdout < 0)
packet_disconnect("dup failed: %.100s", strerror(errno));
/* Add a cleanup function to clear the utmp entry and record logout
time in case we call fatal() (e.g., the connection gets closed). */
/*
* Add a cleanup function to clear the utmp entry and record logout
* time in case we call fatal() (e.g., the connection gets closed).
*/
cleanup_context.pid = pid;
cleanup_context.ttyname = ttyname;
fatal_add_cleanup(pty_cleanup_proc, (void *) &cleanup_context);
@ -2144,9 +2218,11 @@ do_exec_pty(const char *command, int ptyfd, int ttyfd,
/* Release the pseudo-tty. */
pty_release(ttyname);
/* Close the server side of the socket pairs. We must do this
after the pty cleanup, so that another process doesn't get this
pty while we're still cleaning up. */
/*
* Close the server side of the socket pairs. We must do this after
* the pty cleanup, so that another process doesn't get this pty
* while we're still cleaning up.
*/
close(ptyfd);
close(fdout);
}
@ -2162,19 +2238,21 @@ child_set_env(char ***envp, unsigned int *envsizep, const char *name,
unsigned int i, namelen;
char **env;
/* Find the slot where the value should be stored. If the
variable already exists, we reuse the slot; otherwise we append
a new slot at the end of the array, expanding if necessary. */
/*
* Find the slot where the value should be stored. If the variable
* already exists, we reuse the slot; otherwise we append a new slot
* at the end of the array, expanding if necessary.
*/
env = *envp;
namelen = strlen(name);
for (i = 0; env[i]; i++)
if (strncmp(env[i], name, namelen) == 0 && env[i][namelen] == '=')
break;
if (env[i]) {
/* Name already exists. Reuse the slot. */
/* Reuse the slot. */
xfree(env[i]);
} else {
/* New variable. Expand the array if necessary. */
/* New variable. Expand if necessary. */
if (i >= (*envsizep) - 1) {
(*envsizep) += 50;
env = (*envp) = xrealloc(env, (*envsizep) * sizeof(char *));
@ -2202,40 +2280,27 @@ read_environment_file(char ***env, unsigned int *envsize,
char buf[4096];
char *cp, *value;
/* Open the environment file. */
f = fopen(filename, "r");
if (!f)
return;
/* Process each line. */
while (fgets(buf, sizeof(buf), f)) {
/* Skip leading whitespace. */
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++);
/* Ignore empty and comment lines. */
for (cp = buf; *cp == ' ' || *cp == '\t'; cp++)
;
if (!*cp || *cp == '#' || *cp == '\n')
continue;
/* Remove newline. */
if (strchr(cp, '\n'))
*strchr(cp, '\n') = '\0';
/* Find the equals sign. Its lack indicates badly
formatted line. */
value = strchr(cp, '=');
if (value == NULL) {
fprintf(stderr, "Bad line in %.100s: %.200s\n", filename, buf);
continue;
}
/* Replace the equals sign by nul, and advance value to
the value string. */
/* Replace the equals sign by nul, and advance value to the value string. */
*value = '\0';
value++;
/* Set the value in environment. */
child_set_env(env, envsize, cp, value);
}
fclose(f);
}
@ -2299,8 +2364,10 @@ do_child(const char *command, struct passwd * pw, const char *term,
if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid)
fatal("Failed to set uids to %d.", (int) pw->pw_uid);
}
/* Get the shell from the password data. An empty shell field is
legal, and means /bin/sh. */
/*
* Get the shell from the password data. An empty shell field is
* legal, and means /bin/sh.
*/
shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell;
#ifdef AFS
@ -2315,8 +2382,7 @@ do_child(const char *command, struct passwd * pw, const char *term,
}
#endif /* AFS */
/* Initialize the environment. In the first part we allocate
space for all environment variables. */
/* Initialize the environment. */
envsize = 100;
env = xmalloc(envsize * sizeof(char *));
env[0] = NULL;
@ -2335,7 +2401,6 @@ do_child(const char *command, struct passwd * pw, const char *term,
/* Normal systems set SHELL by default. */
child_set_env(&env, &envsize, "SHELL", shell);
}
/* Let it inherit timezone if we have one. */
if (getenv("TZ"))
child_set_env(&env, &envsize, "TZ", getenv("TZ"));
@ -2354,20 +2419,14 @@ do_child(const char *command, struct passwd * pw, const char *term,
xfree(ce);
}
/* Set SSH_CLIENT. */
snprintf(buf, sizeof buf, "%.50s %d %d",
get_remote_ipaddr(), get_remote_port(), options.port);
child_set_env(&env, &envsize, "SSH_CLIENT", buf);
/* Set SSH_TTY if we have a pty. */
if (ttyname)
child_set_env(&env, &envsize, "SSH_TTY", ttyname);
/* Set TERM if we have a pty. */
if (term)
child_set_env(&env, &envsize, "TERM", term);
/* Set DISPLAY if we have one. */
if (display)
child_set_env(&env, &envsize, "DISPLAY", display);
@ -2400,52 +2459,57 @@ do_child(const char *command, struct passwd * pw, const char *term,
}
#endif /* HAVE_LIBPAM */
/* Set XAUTHORITY to always be a local file. */
if (xauthfile)
child_set_env(&env, &envsize, "XAUTHORITY", xauthfile);
/* Set variable for forwarded authentication connection, if we
have one. */
if (auth_get_socket_name() != NULL)
child_set_env(&env, &envsize, SSH_AUTHSOCKET_ENV_NAME,
auth_get_socket_name());
/* Read $HOME/.ssh/environment. */
/* read $HOME/.ssh/environment. */
if (!options.use_login) {
snprintf(buf, sizeof buf, "%.200s/.ssh/environment", pw->pw_dir);
read_environment_file(&env, &envsize, buf);
}
/* If debugging, dump the environment to stderr. */
if (debug_flag) {
/* dump the environment */
fprintf(stderr, "Environment:\n");
for (i = 0; env[i]; i++)
fprintf(stderr, " %.200s\n", env[i]);
}
/* Close the connection descriptors; note that this is the child,
and the server will still have the socket open, and it is
important that we do not shutdown it. Note that the
descriptors cannot be closed before building the environment,
as we call get_remote_ipaddr there. */
/*
* Close the connection descriptors; note that this is the child, and
* the server will still have the socket open, and it is important
* that we do not shutdown it. Note that the descriptors cannot be
* closed before building the environment, as we call
* get_remote_ipaddr there.
*/
if (packet_get_connection_in() == packet_get_connection_out())
close(packet_get_connection_in());
else {
close(packet_get_connection_in());
close(packet_get_connection_out());
}
/* Close all descriptors related to channels. They will still
remain open in the parent. */
/*
* Close all descriptors related to channels. They will still remain
* open in the parent.
*/
/* XXX better use close-on-exec? -markus */
channel_close_all();
/* Close any extra file descriptors. Note that there may still be
descriptors left by system functions. They will be closed
later. */
/*
* Close any extra file descriptors. Note that there may still be
* descriptors left by system functions. They will be closed later.
*/
endpwent();
endhostent();
/* Close any extra open file descriptors so that we don\'t have
them hanging around in clients. Note that we want to do this
after initgroups, because at least on Solaris 2.3 it leaves
file descriptors open. */
/*
* Close any extra open file descriptors so that we don\'t have them
* hanging around in clients. Note that we want to do this after
* initgroups, because at least on Solaris 2.3 it leaves file
* descriptors open.
*/
for (i = 3; i < 64; i++)
close(i);
@ -2454,12 +2518,16 @@ do_child(const char *command, struct passwd * pw, const char *term,
fprintf(stderr, "Could not chdir to home directory %s: %s\n",
pw->pw_dir, strerror(errno));
/* Must take new environment into use so that .ssh/rc, /etc/sshrc
and xauth are run in the proper environment. */
/*
* Must take new environment into use so that .ssh/rc, /etc/sshrc and
* xauth are run in the proper environment.
*/
environ = env;
/* Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found
first in this order). */
/*
* Run $HOME/.ssh/rc, /etc/sshrc, or xauth (whichever is found first
* in this order).
*/
if (!options.use_login) {
if (stat(SSH_USER_RC, &st) >= 0) {
if (debug_flag)
@ -2486,8 +2554,7 @@ do_child(const char *command, struct passwd * pw, const char *term,
}
#ifdef XAUTH_PATH
else {
/* Add authority data to .Xauthority if
appropriate. */
/* Add authority data to .Xauthority if appropriate. */
if (auth_proto != NULL && auth_data != NULL) {
if (debug_flag)
fprintf(stderr, "Running %.100s add %.100s %.100s %.100s\n",
@ -2510,15 +2577,19 @@ do_child(const char *command, struct passwd * pw, const char *term,
else
cp = shell;
}
/* If we have no command, execute the shell. In this case, the
shell name to be passed in argv[0] is preceded by '-' to
indicate that this is a login shell. */
/*
* If we have no command, execute the shell. In this case, the shell
* name to be passed in argv[0] is preceded by '-' to indicate that
* this is a login shell.
*/
if (!command) {
if (!options.use_login) {
char buf[256];
/* Check for mail if we have a tty and it was
enabled in server options. */
/*
* Check for mail if we have a tty and it was enabled
* in server options.
*/
if (ttyname && options.check_mail) {
char *mailbox;
struct stat mailstat;
@ -2558,8 +2629,10 @@ do_child(const char *command, struct passwd * pw, const char *term,
exit(1);
}
}
/* Execute the command using the user's shell. This uses the -c
option to execute the command. */
/*
* Execute the command using the user's shell. This uses the -c
* option to execute the command.
*/
argv[0] = (char *) cp;
argv[1] = "-c";
argv[2] = (char *) command;

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

@ -6,7 +6,7 @@
*/
#include "includes.h"
RCSID("$Id: tildexpand.c,v 1.2 1999/11/24 13:26:23 damien Exp $");
RCSID("$Id: tildexpand.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
#include "xmalloc.h"
#include "ssh.h"
@ -38,7 +38,7 @@ tilde_expand_filename(const char *filename, uid_t my_uid)
else
userlen = strlen(filename); /* Nothing after username. */
if (userlen == 0)
pw = getpwuid(my_uid); /* Own home directory. */
pw = getpwuid(my_uid); /* Own home directory. */
else {
/* Tilde refers to someone elses home directory. */
if (userlen > sizeof(user) - 1)
@ -47,12 +47,12 @@ tilde_expand_filename(const char *filename, uid_t my_uid)
user[userlen] = 0;
pw = getpwnam(user);
}
/* Check that we found the user. */
if (!pw)
fatal("Unknown user %100s.", user);
/* If referring to someones home directory, return it now. */
if (!cp) { /* Only home directory specified */
if (!cp) {
/* Only home directory specified */
return xstrdup(pw->pw_dir);
}
/* Build a path combining the specified directory and path. */

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

@ -10,7 +10,7 @@
*/
#include "includes.h"
RCSID("$Id: ttymodes.c,v 1.2 1999/11/24 13:26:23 damien Exp $");
RCSID("$Id: ttymodes.c,v 1.3 1999/11/25 00:54:59 damien Exp $");
#include "packet.h"
#include "ssh.h"
@ -209,7 +209,6 @@ tty_make_modes(int fd)
struct termios tio;
int baud;
/* Get the modes. */
if (tcgetattr(fd, &tio) < 0) {
packet_put_char(TTY_OP_END);
log("tcgetattr: %.100s", strerror(errno));

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

@ -12,7 +12,7 @@
*
*/
/* RCSID("$Id: ttymodes.h,v 1.2 1999/11/24 13:26:23 damien Exp $"); */
/* RCSID("$Id: ttymodes.h,v 1.3 1999/11/25 00:54:59 damien Exp $"); */
/* The tty mode description is a stream of bytes. The stream consists of
* opcode-arguments pairs. It is terminated by opcode TTY_OP_END (0).
@ -29,112 +29,113 @@
/*
* Some constants and prototypes are defined in packet.h; this file
* is only intended for including from ttymodes.h.
* is only intended for including from ttymodes.c.
*/
/* termios macro *//* sgtty macro */
/* termios macro */ /* sgtty macro */
/* name, op */
TTYCHAR(VINTR, 1) SGTTYCHAR(tiotc.t_intrc, 1)
TTYCHAR(VQUIT, 2) SGTTYCHAR(tiotc.t_quitc, 2)
TTYCHAR(VERASE, 3) SGTTYCHAR(tio.sg_erase, 3)
TTYCHAR(VINTR, 1) SGTTYCHAR(tiotc.t_intrc, 1)
TTYCHAR(VQUIT, 2) SGTTYCHAR(tiotc.t_quitc, 2)
TTYCHAR(VERASE, 3) SGTTYCHAR(tio.sg_erase, 3)
#if defined(VKILL)
TTYCHAR(VKILL, 4) SGTTYCHAR(tio.sg_kill, 4)
#endif /* VKILL */
TTYCHAR(VEOF, 5) SGTTYCHAR(tiotc.t_eofc, 5)
TTYCHAR(VKILL, 4) SGTTYCHAR(tio.sg_kill, 4)
#endif /* VKILL */
TTYCHAR(VEOF, 5) SGTTYCHAR(tiotc.t_eofc, 5)
#if defined(VEOL)
TTYCHAR(VEOL, 6) SGTTYCHAR(tiotc.t_brkc, 6)
#endif /* VEOL */
TTYCHAR(VEOL, 6) SGTTYCHAR(tiotc.t_brkc, 6)
#endif /* VEOL */
#ifdef VEOL2 /* n/a */
TTYCHAR(VEOL2, 7)
#endif /* VEOL2 */
TTYCHAR(VSTART, 8) SGTTYCHAR(tiotc.t_startc, 8)
TTYCHAR(VSTOP, 9) SGTTYCHAR(tiotc.t_stopc, 9)
#endif /* VEOL2 */
TTYCHAR(VSTART, 8) SGTTYCHAR(tiotc.t_startc, 8)
TTYCHAR(VSTOP, 9) SGTTYCHAR(tiotc.t_stopc, 9)
#if defined(VSUSP)
TTYCHAR(VSUSP, 10) SGTTYCHAR(tioltc.t_suspc, 10)
#endif /* VSUSP */
TTYCHAR(VSUSP, 10) SGTTYCHAR(tioltc.t_suspc, 10)
#endif /* VSUSP */
#if defined(VDSUSP)
TTYCHAR(VDSUSP, 11) SGTTYCHAR(tioltc.t_dsuspc, 11)
#endif /* VDSUSP */
TTYCHAR(VDSUSP, 11) SGTTYCHAR(tioltc.t_dsuspc, 11)
#endif /* VDSUSP */
#if defined(VREPRINT)
TTYCHAR(VREPRINT, 12) SGTTYCHAR(tioltc.t_rprntc, 12)
#endif /* VREPRINT */
TTYCHAR(VREPRINT, 12) SGTTYCHAR(tioltc.t_rprntc, 12)
#endif /* VREPRINT */
#if defined(VWERASE)
TTYCHAR(VWERASE, 13) SGTTYCHAR(tioltc.t_werasc, 13)
#endif /* VWERASE */
TTYCHAR(VWERASE, 13) SGTTYCHAR(tioltc.t_werasc, 13)
#endif /* VWERASE */
#if defined(VLNEXT)
TTYCHAR(VLNEXT, 14) SGTTYCHAR(tioltc.t_lnextc, 14)
#endif /* VLNEXT */
TTYCHAR(VLNEXT, 14) SGTTYCHAR(tioltc.t_lnextc, 14)
#endif /* VLNEXT */
#if defined(VFLUSH)
TTYCHAR(VFLUSH, 15) SGTTYCHAR(tioltc.t_flushc, 15)
#endif /* VFLUSH */
TTYCHAR(VFLUSH, 15) SGTTYCHAR(tioltc.t_flushc, 15)
#endif /* VFLUSH */
#ifdef VSWTCH
TTYCHAR(VSWTCH, 16) /* n/a */
#endif /* VSWTCH */
#endif /* VSWTCH */
#if defined(VSTATUS)
TTYCHAR(VSTATUS, 17) SGTTYCHAR(tiots.tc_statusc, 17)
#endif /* VSTATUS */
TTYCHAR(VSTATUS, 17) SGTTYCHAR(tiots.tc_statusc, 17)
#endif /* VSTATUS */
#ifdef VDISCARD
TTYCHAR(VDISCARD, 18) /* n/a */
#endif /* VDISCARD */
#endif /* VDISCARD */
/* name, field, op */
TTYMODE(IGNPAR, c_iflag, 30) /* n/a */
TTYMODE(PARMRK, c_iflag, 31) /* n/a */
TTYMODE(INPCK, c_iflag, 32) SGTTYMODEN(ANYP, tio.sg_flags, 32)
TTYMODE(ISTRIP, c_iflag, 33) SGTTYMODEN(LPASS8, tiolm, 33)
TTYMODE(INLCR, c_iflag, 34) /* n/a */
TTYMODE(IGNCR, c_iflag, 35) /* n/a */
TTYMODE(ICRNL, c_iflag, 36) SGTTYMODE(CRMOD, tio.sg_flags, 36)
TTYMODE(IGNPAR, c_iflag, 30) /* n/a */
TTYMODE(PARMRK, c_iflag, 31) /* n/a */
TTYMODE(INPCK, c_iflag, 32) SGTTYMODEN(ANYP, tio.sg_flags, 32)
TTYMODE(ISTRIP, c_iflag, 33) SGTTYMODEN(LPASS8, tiolm, 33)
TTYMODE(INLCR, c_iflag, 34) /* n/a */
TTYMODE(IGNCR, c_iflag, 35) /* n/a */
TTYMODE(ICRNL, c_iflag, 36) SGTTYMODE(CRMOD, tio.sg_flags, 36)
#if defined(IUCLC)
TTYMODE(IUCLC, c_iflag, 37) SGTTYMODE(LCASE, tio.sg_flags, 37)
TTYMODE(IUCLC, c_iflag, 37) SGTTYMODE(LCASE, tio.sg_flags, 37)
#endif
TTYMODE(IXON, c_iflag, 38) /* n/a */
TTYMODE(IXANY, c_iflag, 39) SGTTYMODEN(LDECCTQ, tiolm, 39)
TTYMODE(IXOFF, c_iflag, 40) SGTTYMODE(TANDEM, tio.sg_flags, 40)
TTYMODE(IXON, c_iflag, 38) /* n/a */
TTYMODE(IXANY, c_iflag, 39) SGTTYMODEN(LDECCTQ, tiolm, 39)
TTYMODE(IXOFF, c_iflag, 40) SGTTYMODE(TANDEM, tio.sg_flags, 40)
#ifdef IMAXBEL
TTYMODE(IMAXBEL, c_iflag, 41) /* n/a */
#endif /* IMAXBEL */
TTYMODE(IMAXBEL,c_iflag, 41) /* n/a */
#endif /* IMAXBEL */
TTYMODE(ISIG, c_lflag, 50) /* n/a */
TTYMODE(ICANON, c_lflag, 51) SGTTYMODEN(CBREAK, tio.sg_flags, 51)
TTYMODE(ISIG, c_lflag, 50) /* n/a */
TTYMODE(ICANON, c_lflag, 51) SGTTYMODEN(CBREAK, tio.sg_flags, 51)
#ifdef XCASE
TTYMODE(XCASE, c_lflag, 52) /* n/a */
TTYMODE(XCASE, c_lflag, 52) /* n/a */
#endif
TTYMODE(ECHO, c_lflag, 53) SGTTYMODE(ECHO, tio.sg_flags, 53)
TTYMODE(ECHOE, c_lflag, 54) SGTTYMODE(LCRTERA, tiolm, 54)
TTYMODE(ECHOK, c_lflag, 55) SGTTYMODE(LCRTKIL, tiolm, 55)
TTYMODE(ECHONL, c_lflag, 56) /* n/a */
TTYMODE(NOFLSH, c_lflag, 57) SGTTYMODE(LNOFLSH, tiolm, 57)
TTYMODE(TOSTOP, c_lflag, 58) SGTTYMODE(LTOSTOP, tiolm, 58)
TTYMODE(ECHO, c_lflag, 53) SGTTYMODE(ECHO, tio.sg_flags, 53)
TTYMODE(ECHOE, c_lflag, 54) SGTTYMODE(LCRTERA, tiolm, 54)
TTYMODE(ECHOK, c_lflag, 55) SGTTYMODE(LCRTKIL, tiolm, 55)
TTYMODE(ECHONL, c_lflag, 56) /* n/a */
TTYMODE(NOFLSH, c_lflag, 57) SGTTYMODE(LNOFLSH, tiolm, 57)
TTYMODE(TOSTOP, c_lflag, 58) SGTTYMODE(LTOSTOP, tiolm, 58)
#ifdef IEXTEN
TTYMODE(IEXTEN, c_lflag, 59) /* n/a */
#endif /* IEXTEN */
#endif /* IEXTEN */
#if defined(ECHOCTL)
TTYMODE(ECHOCTL, c_lflag, 60) SGTTYMODE(LCTLECH, tiolm, 60)
#endif /* ECHOCTL */
TTYMODE(ECHOCTL,c_lflag, 60) SGTTYMODE(LCTLECH, tiolm, 60)
#endif /* ECHOCTL */
#ifdef ECHOKE
TTYMODE(ECHOKE, c_lflag, 61) /* n/a */
#endif /* ECHOKE */
TTYMODE(ECHOKE, c_lflag, 61) /* n/a */
#endif /* ECHOKE */
#if defined(PENDIN)
TTYMODE(PENDIN, c_lflag, 62) SGTTYMODE(LPENDIN, tiolm, 62)
#endif /* PENDIN */
TTYMODE(PENDIN, c_lflag, 62) SGTTYMODE(LPENDIN, tiolm, 62)
#endif /* PENDIN */
TTYMODE(OPOST, c_oflag, 70) /* n/a */
TTYMODE(OPOST, c_oflag, 70) /* n/a */
#if defined(OLCUC)
TTYMODE(OLCUC, c_oflag, 71) SGTTYMODE(LCASE, tio.sg_flags, 71)
TTYMODE(OLCUC, c_oflag, 71) SGTTYMODE(LCASE, tio.sg_flags, 71)
#endif
TTYMODE(ONLCR, c_oflag, 72) SGTTYMODE(CRMOD, tio.sg_flags, 72)
TTYMODE(ONLCR, c_oflag, 72) SGTTYMODE(CRMOD, tio.sg_flags, 72)
#ifdef OCRNL
TTYMODE(OCRNL, c_oflag, 73) /* n/a */
TTYMODE(OCRNL, c_oflag, 73) /* n/a */
#endif
#ifdef ONOCR
TTYMODE(ONOCR, c_oflag, 74) /* n/a */
TTYMODE(ONOCR, c_oflag, 74) /* n/a */
#endif
#ifdef ONLRET
TTYMODE(ONLRET, c_oflag, 75) /* n/a */
TTYMODE(ONLRET, c_oflag, 75) /* n/a */
#endif
TTYMODE(CS7, c_cflag, 90) /* n/a */
TTYMODE(CS8, c_cflag, 91) SGTTYMODE(LPASS8, tiolm, 91)
TTYMODE(PARENB, c_cflag, 92) /* n/a */
TTYMODE(PARODD, c_cflag, 93) SGTTYMODE(ODDP, tio.sg_flags, 93)
TTYMODE(CS7, c_cflag, 90) /* n/a */
TTYMODE(CS8, c_cflag, 91) SGTTYMODE(LPASS8, tiolm, 91)
TTYMODE(PARENB, c_cflag, 92) /* n/a */
TTYMODE(PARODD, c_cflag, 93) SGTTYMODE(ODDP, tio.sg_flags, 93)

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

@ -7,7 +7,7 @@
*/
#include "includes.h"
RCSID("$Id: uidswap.c,v 1.2 1999/11/24 13:26:23 damien Exp $");
RCSID("$Id: uidswap.c,v 1.3 1999/11/25 00:55:00 damien Exp $");
#include "ssh.h"
#include "uidswap.h"
@ -66,10 +66,11 @@ restore_uid()
if (seteuid(saved_euid) < 0)
debug("seteuid %d: %.100s", (int) saved_euid, strerror(errno));
#else /* SAVED_IDS_WORK_WITH_SETEUID */
/* We are unable to restore the real uid to its unprivileged
value. */
/* Propagate the real uid (usually more privileged) to effective
uid as well. */
/*
* We are unable to restore the real uid to its unprivileged value.
* Propagate the real uid (usually more privileged) to effective uid
* as well.
*/
setuid(getuid());
#endif /* SAVED_IDS_WORK_WITH_SETEUID */
}