version 1.26, 1999/11/24 00:26:01 |
version 1.27, 1999/11/24 19:53:45 |
|
|
/* Max len of agent socket */ |
/* Max len of agent socket */ |
#define MAX_SOCKET_NAME 100 |
#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; |
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 |
* Size of the channel array. All slots of the array must always be |
type SSH_CHANNEL_FREE. */ |
* initialized (at least the type field); unused slots are marked with type |
|
* SSH_CHANNEL_FREE. |
|
*/ |
static int channels_alloc = 0; |
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; |
static int channel_max_fd_value = 0; |
|
|
/* Name and directory of socket for authentication agent forwarding. */ |
/* Name and directory of socket for authentication agent forwarding. */ |
|
|
char *x11_saved_data = NULL; |
char *x11_saved_data = NULL; |
unsigned int x11_saved_data_len = 0; |
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; |
char *x11_fake_data = NULL; |
unsigned int x11_fake_data_len; |
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 |
* Data structure for storing which hosts are permitted for forward requests. |
a corrupt remote server from accessing arbitrary TCP/IP ports on our |
* The local sides of any remote forwards are stored in this array to prevent |
local network (which might be behind a firewall). */ |
* a corrupt remote server from accessing arbitrary TCP/IP ports on our local |
|
* network (which might be behind a firewall). |
|
*/ |
typedef struct { |
typedef struct { |
char *host; /* Host name. */ |
char *host; /* Host name. */ |
int port; /* Port number. */ |
int port; /* Port number. */ |
|
|
static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION]; |
static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION]; |
/* Number of permitted host/port pairs in the array. */ |
/* Number of permitted host/port pairs in the array. */ |
static int num_permitted_opens = 0; |
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 |
* If this is true, all opens are permitted. This is the case on the server |
do anything after logging in anyway. */ |
* 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; |
static int all_opens_permitted = 0; |
|
|
/* This is set to true if both sides support SSH_PROTOFLAG_HOST_IN_FWD_OPEN. */ |
/* This is set to true if both sides support SSH_PROTOFLAG_HOST_IN_FWD_OPEN. */ |
|
|
have_hostname_in_open = 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, |
* Permits opening to any host/port in SSH_MSG_PORT_OPEN. This is usually |
and the server has no way to know but to trust the client anyway. */ |
* 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 |
void |
channel_permit_all_opens() |
channel_permit_all_opens() |
|
|
all_opens_permitted = 1; |
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 |
int |
channel_allocate(int type, int sock, char *remote_name) |
channel_allocate(int type, int sock, char *remote_name) |
|
|
/* Update the maximum file descriptor value. */ |
/* Update the maximum file descriptor value. */ |
if (sock > channel_max_fd_value) |
if (sock > channel_max_fd_value) |
channel_max_fd_value = sock; |
channel_max_fd_value = sock; |
|
/* XXX set close-on-exec -markus */ |
|
|
/* Do initial allocation if this is the first call. */ |
/* Do initial allocation if this is the first call. */ |
if (channels_alloc == 0) { |
if (channels_alloc == 0) { |
|
|
channels = xmalloc(channels_alloc * sizeof(Channel)); |
channels = xmalloc(channels_alloc * sizeof(Channel)); |
for (i = 0; i < channels_alloc; i++) |
for (i = 0; i < channels_alloc; i++) |
channels[i].type = SSH_CHANNEL_FREE; |
channels[i].type = SSH_CHANNEL_FREE; |
|
/* |
/* Kludge: arrange a call to channel_stop_listening if we |
* Kludge: arrange a call to channel_stop_listening if we |
terminate with fatal(). */ |
* terminate with fatal(). |
|
*/ |
fatal_add_cleanup((void (*) (void *)) channel_stop_listening, NULL); |
fatal_add_cleanup((void (*) (void *)) channel_stop_listening, NULL); |
} |
} |
/* Try to find a free slot where to put the new channel. */ |
/* Try to find a free slot where to put the new channel. */ |
|
|
break; |
break; |
} |
} |
if (found == -1) { |
if (found == -1) { |
/* There are no free slots. Take last+1 slot and expand |
/* There are no free slots. Take last+1 slot and expand the array. */ |
the array. */ |
|
found = channels_alloc; |
found = channels_alloc; |
channels_alloc += 10; |
channels_alloc += 10; |
debug("channel: expanding %d", channels_alloc); |
debug("channel: expanding %d", channels_alloc); |
|
|
} |
} |
} |
} |
|
|
/* 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 |
void |
channel_prepare_select(fd_set * readset, fd_set * writeset) |
channel_prepare_select(fd_set * readset, fd_set * writeset) |
|
|
break; |
break; |
|
|
case SSH_CHANNEL_X11_OPEN: |
case SSH_CHANNEL_X11_OPEN: |
/* This is a special state for X11 authentication |
/* |
spoofing. An opened X11 connection (when |
* This is a special state for X11 authentication |
authentication spoofing is being done) remains |
* spoofing. An opened X11 connection (when |
in this state until the first packet has been |
* authentication spoofing is being done) remains in |
completely read. The authentication data in |
* this state until the first packet has been |
that packet is then substituted by the real |
* completely read. The authentication data in that |
data if it matches the fake data, and the |
* packet is then substituted by the real data if it |
channel is put into normal mode. */ |
* matches the fake data, and the channel is put into |
|
* normal mode. |
|
*/ |
/* Check if the fixed size part of the packet is in buffer. */ |
/* Check if the fixed size part of the packet is in buffer. */ |
if (buffer_len(&ch->output) < 12) |
if (buffer_len(&ch->output) < 12) |
break; |
break; |
|
|
ch->type = SSH_CHANNEL_OPEN; |
ch->type = SSH_CHANNEL_OPEN; |
goto reject; |
goto reject; |
} |
} |
/* Received authentication protocol and data match |
/* |
our fake data. Substitute the fake data with |
* Received authentication protocol and data match |
real data. */ |
* our fake data. Substitute the fake data with real |
|
* data. |
|
*/ |
memcpy(ucp + 12 + ((proto_len + 3) & ~3), |
memcpy(ucp + 12 + ((proto_len + 3) & ~3), |
x11_saved_data, x11_saved_data_len); |
x11_saved_data, x11_saved_data_len); |
|
|
|
|
goto redo; |
goto redo; |
|
|
reject: |
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"); |
log("X11 connection rejected because of wrong authentication.\r\n"); |
buffer_clear(&ch->input); |
buffer_clear(&ch->input); |
buffer_clear(&ch->output); |
buffer_clear(&ch->output); |
|
|
} |
} |
} |
} |
|
|
/* 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 |
void |
channel_after_select(fd_set * readset, fd_set * writeset) |
channel_after_select(fd_set * readset, fd_set * writeset) |
|
|
break; |
break; |
|
|
case SSH_CHANNEL_PORT_LISTENER: |
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)) { |
if (FD_ISSET(ch->sock, readset)) { |
debug("Connection to port %d forwarding to %.100s:%d requested.", |
debug("Connection to port %d forwarding to %.100s:%d requested.", |
ch->listening_port, ch->path, ch->host_port); |
ch->listening_port, ch->path, ch->host_port); |
|
|
break; |
break; |
|
|
case SSH_CHANNEL_AUTH_SOCKET: |
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)) { |
if (FD_ISSET(ch->sock, readset)) { |
int nchan; |
int nchan; |
len = sizeof(addr); |
len = sizeof(addr); |
|
|
break; |
break; |
|
|
case SSH_CHANNEL_OPEN: |
case SSH_CHANNEL_OPEN: |
/* This is an open two-way communication channel. |
/* |
It is not of interest to us at this point what |
* This is an open two-way communication channel. It |
kind of data is being transmitted. */ |
* 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 |
* Read available incoming data and append it to |
failes */ |
* buffer; shutdown socket, if read or write failes |
|
*/ |
if (FD_ISSET(ch->sock, readset)) { |
if (FD_ISSET(ch->sock, readset)) { |
len = read(ch->sock, buf, sizeof(buf)); |
len = read(ch->sock, buf, sizeof(buf)); |
if (len <= 0) { |
if (len <= 0) { |
|
|
|
|
for (i = 0; i < channels_alloc; i++) { |
for (i = 0; i < channels_alloc; i++) { |
ch = &channels[i]; |
ch = &channels[i]; |
/* We are only interested in channels that can have |
/* We are only interested in channels that can have buffered incoming data. */ |
buffered incoming data. */ |
|
if (ch->type != SSH_CHANNEL_OPEN && |
if (ch->type != SSH_CHANNEL_OPEN && |
ch->type != SSH_CHANNEL_INPUT_DRAINING) |
ch->type != SSH_CHANNEL_INPUT_DRAINING) |
continue; |
continue; |
|
|
/* Get the amount of buffered data for this channel. */ |
/* Get the amount of buffered data for this channel. */ |
len = buffer_len(&ch->input); |
len = buffer_len(&ch->input); |
if (len > 0) { |
if (len > 0) { |
/* Send some data for the other side over the |
/* Send some data for the other side over the secure connection. */ |
secure connection. */ |
|
if (packet_is_interactive()) { |
if (packet_is_interactive()) { |
if (len > 1024) |
if (len > 1024) |
len = 512; |
len = 512; |
|
|
} else if (ch->istate == CHAN_INPUT_WAIT_DRAIN) { |
} else if (ch->istate == CHAN_INPUT_WAIT_DRAIN) { |
if (compat13) |
if (compat13) |
fatal("cannot happen: istate == INPUT_WAIT_DRAIN for proto 1.3"); |
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: |
* input-buffer is empty and read-socket shutdown: |
send IEOF */ |
* tell peer, that we will not send more data: send IEOF |
|
*/ |
chan_ibuf_empty(ch); |
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 |
* This is called when a packet of type CHANNEL_DATA has just been received. |
is still there. */ |
* The message type has already been consumed, but channel number and data is |
|
* still there. |
|
*/ |
|
|
void |
void |
channel_input_data(int payload_len) |
channel_input_data(int payload_len) |
|
|
xfree(data); |
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 |
int |
channel_not_very_much_buffered_data() |
channel_not_very_much_buffered_data() |
|
|
chan_rcvd_ieof(&channels[channel]); |
chan_rcvd_ieof(&channels[channel]); |
return; |
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_start(SSH_MSG_CHANNEL_CLOSE_CONFIRMATION); |
packet_put_int(channels[channel].remote_id); |
packet_put_int(channels[channel].remote_id); |
packet_send(); |
packet_send(); |
|
|
/* If the channel is in closed state, we have sent a close |
/* |
request, and the other side will eventually respond with a |
* If the channel is in closed state, we have sent a close request, |
confirmation. Thus, we cannot free the channel here, because |
* and the other side will eventually respond with a confirmation. |
then there would be no-one to receive the confirmation. The |
* Thus, we cannot free the channel here, because then there would be |
channel gets freed when the confirmation arrives. */ |
* no-one to receive the confirmation. The channel gets freed when |
|
* the confirmation arrives. |
|
*/ |
if (channels[channel].type != SSH_CHANNEL_CLOSED) { |
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_consume(&channels[channel].input, |
buffer_len(&channels[channel].input)); |
buffer_len(&channels[channel].input)); |
channels[channel].type = SSH_CHANNEL_OUTPUT_DRAINING; |
channels[channel].type = SSH_CHANNEL_OUTPUT_DRAINING; |
|
|
/* Get remote side's id for this channel. */ |
/* Get remote side's id for this channel. */ |
remote_channel = packet_get_int(); |
remote_channel = packet_get_int(); |
|
|
/* Record the remote channel number and mark that the channel is |
/* Record the remote channel number and mark that the channel is now open. */ |
now open. */ |
|
channels[channel].remote_id = remote_channel; |
channels[channel].remote_id = remote_channel; |
channels[channel].type = SSH_CHANNEL_OPEN; |
channels[channel].type = SSH_CHANNEL_OPEN; |
} |
} |
|
|
channel_free(channel); |
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 |
void |
channel_stop_listening() |
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 |
void |
channel_close_all() |
channel_close_all() |
|
|
return 0; |
return 0; |
} |
} |
|
|
/* Returns a message describing the currently open forwarded |
/* |
connections, suitable for sending to the client. The message |
* Returns a message describing the currently open forwarded connections, |
contains crlf pairs for newlines. */ |
* suitable for sending to the client. The message contains crlf pairs for |
|
* newlines. |
|
*/ |
|
|
char * |
char * |
channel_open_message() |
channel_open_message() |
|
|
return cp; |
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 |
void |
channel_request_local_forwarding(int port, const char *host, |
channel_request_local_forwarding(int port, const char *host, |
|
|
channels[ch].listening_port = port; |
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 |
void |
channel_request_remote_forwarding(int port, const char *host, |
channel_request_remote_forwarding(int port, const char *host, |
|
|
packet_send(); |
packet_send(); |
packet_write_wait(); |
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); |
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 |
* This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates |
message if there was an error). This never returns if there was an |
* listening for the port, and sends back a success reply (or disconnect |
error. */ |
* message if there was an error). This never returns if there was an error. |
|
*/ |
|
|
void |
void |
channel_input_port_forward_request(int is_root) |
channel_input_port_forward_request(int is_root) |
|
|
if ((port & 0xffff) != port) |
if ((port & 0xffff) != port) |
packet_disconnect("Requested forwarding of nonexistent port %d.", 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) |
if (port < IPPORT_RESERVED && !is_root) |
packet_disconnect("Requested forwarding of port %d but user is not root.", |
packet_disconnect("Requested forwarding of port %d but user is not root.", |
port); |
port); |
|
|
xfree(hostname); |
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 |
* This is called after receiving PORT_OPEN message. This attempts to |
CHANNEL_OPEN_FAILURE. */ |
* connect to the given host:port, and sends back CHANNEL_OPEN_CONFIRMATION |
|
* or CHANNEL_OPEN_FAILURE. |
|
*/ |
|
|
void |
void |
channel_input_port_open(int payload_len) |
channel_input_port_open(int payload_len) |
|
|
packet_send(); |
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 |
* Creates an internet domain socket for listening for X11 connections. |
occurs. */ |
* Returns a suitable value for the DISPLAY variable, or NULL if an error |
|
* occurs. |
|
*/ |
|
|
char * |
char * |
x11_create_display_inet(int screen_number) |
x11_create_display_inet(int screen_number) |
|
|
} |
} |
|
|
|
|
/* 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 |
* This is called when SSH_SMSG_X11_OPEN is received. The packet contains |
with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. */ |
* the remote channel number. We should do whatever we want, and respond |
|
* with either SSH_MSG_OPEN_CONFIRMATION or SSH_MSG_OPEN_FAILURE. |
|
*/ |
|
|
void |
void |
x11_input_open(int payload_len) |
x11_input_open(int payload_len) |
|
|
error("DISPLAY not set."); |
error("DISPLAY not set."); |
goto fail; |
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 || |
if (strncmp(display, "unix:", 5) == 0 || |
display[0] == ':') { |
display[0] == ':') { |
/* Connect to the unix domain socket. */ |
/* Connect to the unix domain socket. */ |
|
|
/* OK, we now have a connection to the display. */ |
/* OK, we now have a connection to the display. */ |
goto success; |
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)); |
strncpy(buf, display, sizeof(buf)); |
buf[sizeof(buf) - 1] = 0; |
buf[sizeof(buf) - 1] = 0; |
cp = strchr(buf, ':'); |
cp = strchr(buf, ':'); |
|
|
goto fail; |
goto fail; |
} |
} |
*cp = 0; |
*cp = 0; |
/* buf now contains the host name. But first we parse the display |
/* buf now contains the host name. But first we parse the display number. */ |
number. */ |
|
if (sscanf(cp + 1, "%d", &display_number) != 1) { |
if (sscanf(cp + 1, "%d", &display_number) != 1) { |
error("Could not parse display number from DISPLAY: %.100s", |
error("Could not parse display number from DISPLAY: %.100s", |
display); |
display); |
|
|
packet_send(); |
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 |
void |
x11_request_forwarding_with_spoofing(const char *proto, const char *data) |
x11_request_forwarding_with_spoofing(const char *proto, const char *data) |
|
|
/* Save protocol name. */ |
/* Save protocol name. */ |
x11_saved_proto = xstrdup(proto); |
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_saved_data = xmalloc(data_len); |
x11_fake_data = xmalloc(data_len); |
x11_fake_data = xmalloc(data_len); |
for (i = 0; i < data_len; i++) { |
for (i = 0; i < data_len; i++) { |
|
|
packet_write_wait(); |
packet_write_wait(); |
} |
} |
|
|
/* Returns the name of the forwarded authentication socket. Returns NULL |
/* |
if there is no forwarded authentication socket. The returned value |
* Returns the name of the forwarded authentication socket. Returns NULL if |
points to a static buffer. */ |
* there is no forwarded authentication socket. The returned value points to |
|
* a static buffer. |
|
*/ |
|
|
char * |
char * |
auth_get_socket_name() |
auth_get_socket_name() |
|
|
rmdir(channel_forwarded_auth_socket_dir); |
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 |
void |
auth_input_request_forwarding(struct passwd * pw) |
auth_input_request_forwarding(struct passwd * pw) |
|
|
/* Read the remote channel number from the message. */ |
/* Read the remote channel number from the message. */ |
remch = packet_get_int(); |
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(); |
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, |
* If we could not connect the agent, send an error message back to |
because authentication forwarding is only enabled if we have an |
* the server. This should never happen unless the agent dies, |
agent. */ |
* because authentication forwarding is only enabled if we have an |
|
* agent. |
|
*/ |
if (sock < 0) { |
if (sock < 0) { |
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); |
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); |
packet_put_int(remch); |
packet_put_int(remch); |
|
|
} |
} |
debug("Forwarding authentication connection."); |
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 |
* Dummy host name. This will be freed when the channel is freed; it |
channel cannot yet be freed at that point. */ |
* 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"); |
dummyname = xstrdup("authentication agent connection"); |
|
|
newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname); |
newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname); |