mirror of
https://git.libssh.org/projects/libssh.git
synced 2026-02-09 09:54:25 +09:00
misc: Add support for %j and %C percent expand
Signed-off-by: Jakub Jelen <jjelen@redhat.com> Reviewed-by: Pavol Žáčik <pzacik@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
@@ -250,6 +250,7 @@ struct ssh_session_struct {
|
|||||||
struct ssh_list *certificate_non_exp;
|
struct ssh_list *certificate_non_exp;
|
||||||
struct ssh_list *proxy_jumps;
|
struct ssh_list *proxy_jumps;
|
||||||
struct ssh_list *proxy_jumps_user_cb;
|
struct ssh_list *proxy_jumps_user_cb;
|
||||||
|
char *proxy_jumps_str;
|
||||||
char *username;
|
char *username;
|
||||||
char *host;
|
char *host;
|
||||||
char *bindaddr; /* bind the client to an ip addr */
|
char *bindaddr; /* bind the client to an ip addr */
|
||||||
|
|||||||
15
src/config.c
15
src/config.c
@@ -493,6 +493,10 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing)
|
|||||||
bool parse_entry = do_parsing;
|
bool parse_entry = do_parsing;
|
||||||
bool libssh_proxy_jump = ssh_libssh_proxy_jumps();
|
bool libssh_proxy_jump = ssh_libssh_proxy_jumps();
|
||||||
|
|
||||||
|
if (do_parsing) {
|
||||||
|
SAFE_FREE(session->opts.proxy_jumps_str);
|
||||||
|
ssh_proxyjumps_free(session->opts.proxy_jumps);
|
||||||
|
}
|
||||||
/* Special value none disables the proxy */
|
/* Special value none disables the proxy */
|
||||||
cmp = strcasecmp(s, "none");
|
cmp = strcasecmp(s, "none");
|
||||||
if (cmp == 0) {
|
if (cmp == 0) {
|
||||||
@@ -509,6 +513,17 @@ ssh_config_parse_proxy_jump(ssh_session session, const char *s, bool do_parsing)
|
|||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (do_parsing) {
|
||||||
|
/* Store the whole string in sesion */
|
||||||
|
SAFE_FREE(session->opts.proxy_jumps_str);
|
||||||
|
session->opts.proxy_jumps_str = strdup(s);
|
||||||
|
if (session->opts.proxy_jumps_str == NULL) {
|
||||||
|
free(c);
|
||||||
|
ssh_set_error_oom(session);
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cp = c;
|
cp = c;
|
||||||
do {
|
do {
|
||||||
endp = strchr(cp, ',');
|
endp = strchr(cp, ',');
|
||||||
|
|||||||
155
src/misc.c
155
src/misc.c
@@ -490,6 +490,38 @@ char *ssh_hostport(const char *host, int port)
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
ssh_get_hexa_internal(const unsigned char *what, size_t len, bool colons)
|
||||||
|
{
|
||||||
|
const char h[] = "0123456789abcdef";
|
||||||
|
char *hexa = NULL;
|
||||||
|
size_t i;
|
||||||
|
size_t bytes_per_byte = 2 + (colons ? 1 : 0);
|
||||||
|
size_t hlen = len * bytes_per_byte;
|
||||||
|
|
||||||
|
if (len > (UINT_MAX - 1) / bytes_per_byte) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hexa = calloc(hlen + 1, sizeof(char));
|
||||||
|
if (hexa == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
hexa[i * bytes_per_byte] = h[(what[i] >> 4) & 0xF];
|
||||||
|
hexa[i * bytes_per_byte + 1] = h[what[i] & 0xF];
|
||||||
|
if (colons) {
|
||||||
|
hexa[i * bytes_per_byte + 2] = ':';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (colons) {
|
||||||
|
hexa[hlen - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return hexa;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Convert a buffer into a colon separated hex string.
|
* @brief Convert a buffer into a colon separated hex string.
|
||||||
* The caller has to free the memory.
|
* The caller has to free the memory.
|
||||||
@@ -505,28 +537,7 @@ char *ssh_hostport(const char *host, int port)
|
|||||||
*/
|
*/
|
||||||
char *ssh_get_hexa(const unsigned char *what, size_t len)
|
char *ssh_get_hexa(const unsigned char *what, size_t len)
|
||||||
{
|
{
|
||||||
const char h[] = "0123456789abcdef";
|
return ssh_get_hexa_internal(what, len, true);
|
||||||
char *hexa = NULL;
|
|
||||||
size_t i;
|
|
||||||
size_t hlen = len * 3;
|
|
||||||
|
|
||||||
if (len > (UINT_MAX - 1) / 3) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
hexa = malloc(hlen + 1);
|
|
||||||
if (hexa == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
hexa[i * 3] = h[(what[i] >> 4) & 0xF];
|
|
||||||
hexa[i * 3 + 1] = h[what[i] & 0xF];
|
|
||||||
hexa[i * 3 + 2] = ':';
|
|
||||||
}
|
|
||||||
hexa[hlen - 1] = '\0';
|
|
||||||
|
|
||||||
return hexa;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1245,15 +1256,93 @@ char *ssh_get_local_hostname(void)
|
|||||||
return strdup(host);
|
return strdup(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *get_connection_hash(ssh_session session)
|
||||||
|
{
|
||||||
|
unsigned char conn_hash[SHA_DIGEST_LENGTH];
|
||||||
|
char *local_hostname = NULL;
|
||||||
|
SHACTX ctx = sha1_init();
|
||||||
|
char strport[10] = {0};
|
||||||
|
unsigned int port;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (session == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Local hostname %l */
|
||||||
|
local_hostname = ssh_get_local_hostname();
|
||||||
|
if (local_hostname == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
rc = sha1_update(ctx, local_hostname, strlen(local_hostname));
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
SAFE_FREE(local_hostname);
|
||||||
|
|
||||||
|
/* Remote hostname %h */
|
||||||
|
rc = sha1_update(ctx, session->opts.host, strlen(session->opts.host));
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remote port %p */
|
||||||
|
ssh_options_get_port(session, &port);
|
||||||
|
snprintf(strport, sizeof(strport), "%d", port);
|
||||||
|
rc = sha1_update(ctx, strport, strlen(strport));
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The remote username %r */
|
||||||
|
rc = sha1_update(ctx,
|
||||||
|
session->opts.username,
|
||||||
|
strlen(session->opts.username));
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ProxyJump */
|
||||||
|
if (session->opts.proxy_jumps_str != NULL) {
|
||||||
|
rc = sha1_update(ctx,
|
||||||
|
session->opts.proxy_jumps_str,
|
||||||
|
strlen(session->opts.proxy_jumps_str));
|
||||||
|
}
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Frees context */
|
||||||
|
rc = sha1_final(conn_hash, ctx);
|
||||||
|
if (rc != SSH_OK) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssh_get_hexa_internal(conn_hash, SHA_DIGEST_LENGTH, false);
|
||||||
|
|
||||||
|
err:
|
||||||
|
free(local_hostname);
|
||||||
|
sha1_ctx_free(ctx);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/** @internal
|
/** @internal
|
||||||
* @brief expands a string in function of session options
|
* @brief expands a string in function of session options
|
||||||
|
*
|
||||||
* @param[in] s Format string to expand. Known parameters:
|
* @param[in] s Format string to expand. Known parameters:
|
||||||
* %d user home directory (~)
|
* - %d user home directory (~)
|
||||||
* %h target host name
|
* - %h target host name
|
||||||
* %u local username
|
* - %u local username
|
||||||
* %l local hostname
|
* - %l local hostname
|
||||||
* %r remote username
|
* - %r remote username
|
||||||
* %p remote port
|
* - %p remote port
|
||||||
|
* - %j proxyjump string
|
||||||
|
* - %C Hash of %l%h%p%r%j
|
||||||
|
*
|
||||||
* @returns Expanded string. The caller needs to free the memory using
|
* @returns Expanded string. The caller needs to free the memory using
|
||||||
* ssh_string_free_char().
|
* ssh_string_free_char().
|
||||||
*
|
*
|
||||||
@@ -1355,6 +1444,16 @@ char *ssh_path_expand_escape(ssh_session session, const char *s)
|
|||||||
x = strdup(tmp);
|
x = strdup(tmp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'j':
|
||||||
|
if (session->opts.proxy_jumps_str != NULL) {
|
||||||
|
x = strdup(session->opts.proxy_jumps_str);
|
||||||
|
} else {
|
||||||
|
x = strdup("");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
x = get_connection_hash(session);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
ssh_set_error(session, SSH_FATAL, "Wrong escape sequence detected");
|
ssh_set_error(session, SSH_FATAL, "Wrong escape sequence detected");
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|||||||
@@ -384,6 +384,7 @@ void ssh_free(ssh_session session)
|
|||||||
ssh_proxyjumps_free(session->opts.proxy_jumps);
|
ssh_proxyjumps_free(session->opts.proxy_jumps);
|
||||||
SSH_LIST_FREE(session->opts.proxy_jumps);
|
SSH_LIST_FREE(session->opts.proxy_jumps);
|
||||||
SSH_LIST_FREE(session->opts.proxy_jumps_user_cb);
|
SSH_LIST_FREE(session->opts.proxy_jumps_user_cb);
|
||||||
|
SAFE_FREE(session->opts.proxy_jumps_str);
|
||||||
|
|
||||||
while ((b = ssh_list_pop_head(struct ssh_buffer_struct *,
|
while ((b = ssh_list_pop_head(struct ssh_buffer_struct *,
|
||||||
session->out_queue)) != NULL) {
|
session->out_queue)) != NULL) {
|
||||||
|
|||||||
Reference in New Issue
Block a user