Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GUACAMOLE-312: Add guacd support for tunneling connections over SSH #534

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/common-ssh/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

AUTOMAKE_OPTIONS = foreign
ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -DGUACD_STATE_DIR='"$(localstatedir)/run/guacd"'

noinst_LTLIBRARIES = libguac_common_ssh.la
SUBDIRS = . tests
Expand All @@ -34,13 +35,15 @@ libguac_common_ssh_la_SOURCES = \
sftp.c \
ssh.c \
key.c \
tunnel.c \
user.c

noinst_HEADERS = \
common-ssh/buffer.h \
common-ssh/key.h \
common-ssh/sftp.h \
common-ssh/ssh.h \
common-ssh/tunnel.h \
common-ssh/user.h

libguac_common_ssh_la_CFLAGS = \
Expand Down
2 changes: 2 additions & 0 deletions src/common-ssh/common-ssh/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <guacamole/client.h>
#include <libssh2.h>

#define GUAC_COMMON_SSH_KEY_DEFAULT_KNOWN_HOSTS "/etc/guacamole/ssh_known_hosts"

/**
* OpenSSH v1 private keys are PEM-wrapped base64-encoded blobs. The encoded data begins with:
* "openssh-key-v1\0"
Expand Down
40 changes: 40 additions & 0 deletions src/common-ssh/common-ssh/ssh-constants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#ifndef GUAC_COMMON_SSH_CONSTANTS_H
#define GUAC_COMMON_SSH_CONSTANTS_H

/**
* The default port to use for SSH and SFTP connections.
*/
#define GUAC_COMMON_SSH_DEFAULT_PORT "22"

/**
* The default interval at which to send keepalives, which is zero, where
* keepalives will not be sent.
*/
#define GUAC_COMMON_SSH_DEFAULT_ALIVE_INTERVAL 0

/**
* For SFTP connections, the default root directory at which to start
* the session.
*/
#define GUAC_COMMON_SSH_SFTP_DEFAULT_ROOT "/"

#endif
117 changes: 117 additions & 0 deletions src/common-ssh/common-ssh/tunnel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#ifndef GUAC_COMMON_SSH_TUNNEL_H
#define GUAC_COMMON_SSH_TUNNEL_H

#include "common-ssh/ssh.h"

#include <libssh2.h>
#include <pthread.h>

/**
* Default backlog size for the socket used for the SSH tunnel.
*/
#define GUAC_COMMON_SSH_TUNNEL_BACKLOG_SIZE 8

/**
* The default directory mode that will be used to create the directory that
* will store the sockets.
*/
#define GUAC_COMMON_SSH_TUNNEL_DIRECTORY_MODE 0700

/**
* The default mode of the file that will be used to access the UNIX domain
* socket.
*/
#define GUAC_COMMON_SSH_TUNNEL_SOCKET_MODE 0600

/**
* A data structure that contains the elements needed to be passed between
* the various Guacamole Client protocol implementations and the common SSH
* tunnel code.
*/
typedef struct guac_ssh_tunnel {

/**
* The Guacamole Client that is using this SSH tunnel.
*/
guac_client* client;

/**
* The user and credentials for authenticating the SSH tunnel.
*/
guac_common_ssh_user* user;

/**
* The SSH session to use to tunnel the data.
*/
guac_common_ssh_session* session;

/**
* The libssh2 channel that will carry the tunnel data over the SSH connection.
*/
LIBSSH2_CHANNEL *channel;

/**
* The path to the local socket that will be used by guacd to communicate
* with the SSH tunnel.
*/
char* socket_path;

} guac_ssh_tunnel;

/**
* Initialize the SSH tunnel to the given host and port combination through
* the provided SSH session, and open a socket at the specified path for the
* communication. This function will place the absolute path of the domain
* socket in the socket_path variable and return zero on success or non-zero
* on failure.
*
* @param ssh_tunnel
* The data structure containing relevant SSH tunnel information, including
* the guac_client that initialized the tunnel and the various libssh2
* session and channel objects.
*
* @param host
* The hostname or IP address to connect to over the tunnel.
*
* @param port
* The TCP port to connect to over the tunnel.
*
* @return
* Zero on success, non-zero on failure.
*/
int guac_common_ssh_tunnel_init(guac_ssh_tunnel* ssh_tunnel,
char* remote_host,
int remote_port);

/**
* Clean up the SSH tunnel, shutting down the channel and freeing the
* various data items created for the tunnel.
*
* @param ssh_tunnel
* The guac_common_ssh_session used to establish the tunnel.
*
* @return
* Zero on success, non-zero on failure.
*/
int guac_common_ssh_tunnel_cleanup(guac_ssh_tunnel* ssh_tunnel);

#endif
2 changes: 1 addition & 1 deletion src/common-ssh/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ int guac_common_ssh_verify_host_key(LIBSSH2_SESSION* session, guac_client* clien
/* Otherwise, we look for a ssh_known_hosts file within GUACAMOLE_HOME and read that in. */
else {

const char *guac_known_hosts = "/etc/guacamole/ssh_known_hosts";
const char *guac_known_hosts = GUAC_COMMON_SSH_KEY_DEFAULT_KNOWN_HOSTS;
if (access(guac_known_hosts, F_OK) != -1)
known_hosts = libssh2_knownhost_readfile(ssh_known_hosts, guac_known_hosts, LIBSSH2_KNOWNHOST_FILE_OPENSSH);

Expand Down
15 changes: 13 additions & 2 deletions src/common-ssh/ssh.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <guacamole/fips.h>
#include <guacamole/mem.h>
#include <guacamole/socket-tcp.h>
#include <guacamole/socket-unix.h>
#include <guacamole/string.h>
#include <libssh2.h>

Expand Down Expand Up @@ -411,10 +412,20 @@ guac_common_ssh_session* guac_common_ssh_create_session(guac_client* client,
int keepalive, const char* host_key,
guac_ssh_credential_handler* credential_handler) {

int fd = guac_socket_tcp_connect(hostname, port);
int fd;
struct stat sb;

/* Hostname is a UNIX socket */
if (stat(hostname, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFSOCK)
fd = guac_socket_unix_connect(hostname);

/* Hostname is IP-based */
else
fd = guac_socket_tcp_connect(hostname, port);

if (fd < 0) {
guac_client_abort(client, GUAC_PROTOCOL_STATUS_SERVER_ERROR,
"Failed to open TCP connection to %s on %s.", hostname, port);
"Failed to open SSH connection to %s on %s", hostname, port);
return NULL;
}

Expand Down
Loading
Loading