1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-11-29 01:03:57 +03:00

Add a placehohlder for non-expanded identities

Expanding a string twice could lead to unwanted behaviour.
This solution creates a ssh_list (`opts.identites_non_exp`) to store the strings
before expansion and by using ssh_apply it moves the string to the
`opts.identities`. This way the expanded strings are separated.

Signed-off-by: Norbert Pocs <npocs@redhat.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
Norbert Pocs
2022-11-16 10:40:38 +01:00
committed by Jakub Jelen
parent 435f1549f1
commit 1ff893c914
3 changed files with 75 additions and 35 deletions

View File

@@ -209,6 +209,7 @@ struct ssh_session_struct {
#endif #endif
struct { struct {
struct ssh_list *identity; struct ssh_list *identity;
struct ssh_list *identity_non_exp;
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 */

View File

@@ -52,7 +52,7 @@
* @brief Duplicate the options of a session structure. * @brief Duplicate the options of a session structure.
* *
* If you make several sessions with the same options this is useful. You * If you make several sessions with the same options this is useful. You
* cannot use twice the same option structure in ssh_session_connect. * cannot use twice the same option structure in ssh_connect.
* *
* @param src The session to use to copy the options. * @param src The session to use to copy the options.
* *
@@ -61,13 +61,14 @@
* *
* @returns 0 on success, -1 on error with errno set. * @returns 0 on success, -1 on error with errno set.
* *
* @see ssh_session_connect() * @see ssh_connect()
* @see ssh_free() * @see ssh_free()
*/ */
int ssh_options_copy(ssh_session src, ssh_session *dest) int ssh_options_copy(ssh_session src, ssh_session *dest)
{ {
ssh_session new; ssh_session new;
struct ssh_iterator *it = NULL; struct ssh_iterator *it = NULL;
struct ssh_list *list = NULL;
char *id = NULL; char *id = NULL;
int i; int i;
@@ -105,14 +106,15 @@ int ssh_options_copy(ssh_session src, ssh_session *dest)
} }
/* Remove the default identities */ /* Remove the default identities */
for (id = ssh_list_pop_head(char *, new->opts.identity); for (id = ssh_list_pop_head(char *, new->opts.identity_non_exp);
id != NULL; id != NULL;
id = ssh_list_pop_head(char *, new->opts.identity)) { id = ssh_list_pop_head(char *, new->opts.identity_non_exp)) {
SAFE_FREE(id); SAFE_FREE(id);
} }
/* Copy the new identities from the source list */ /* Copy the new identities from the source list */
if (src->opts.identity != NULL) { list = new->opts.identity_non_exp;
it = ssh_list_get_iterator(src->opts.identity); it = ssh_list_get_iterator(src->opts.identity_non_exp);
for (i = 0; i < 2; i++) {
while (it) { while (it) {
int rc; int rc;
@@ -122,7 +124,7 @@ int ssh_options_copy(ssh_session src, ssh_session *dest)
return -1; return -1;
} }
rc = ssh_list_append(new->opts.identity, id); rc = ssh_list_append(list, id);
if (rc < 0) { if (rc < 0) {
free(id); free(id);
ssh_free(new); ssh_free(new);
@@ -130,6 +132,10 @@ int ssh_options_copy(ssh_session src, ssh_session *dest)
} }
it = it->next; it = it->next;
} }
/* copy the identity list if there is any already */
list = new->opts.identity;
it = ssh_list_get_iterator(src->opts.identity);
} }
if (src->opts.sshdir != NULL) { if (src->opts.sshdir != NULL) {
@@ -331,7 +337,7 @@ int ssh_options_set_algo(ssh_session session,
* Add a new identity file (const char *, format string) to * Add a new identity file (const char *, format string) to
* the identity list.\n * the identity list.\n
* \n * \n
* By default identity, id_dsa and id_rsa are checked.\n * By default id_rsa, id_ecdsa and id_ed25519 files are used.\n
* \n * \n
* The identity used to authenticate with public key will be * The identity used to authenticate with public key will be
* prepended to the list. * prepended to the list.
@@ -705,7 +711,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
if (q == NULL) { if (q == NULL) {
return -1; return -1;
} }
rc = ssh_list_prepend(session->opts.identity, q); if (session->opts.exp_flags & SSH_OPT_EXP_FLAG_IDENTITY) {
rc = ssh_list_append(session->opts.identity_non_exp, q);
} else {
rc = ssh_list_prepend(session->opts.identity_non_exp, q);
}
if (rc < 0) { if (rc < 0) {
free(q); free(q);
return -1; return -1;
@@ -1216,7 +1226,7 @@ int ssh_options_get_port(ssh_session session, unsigned int* port_target) {
* - SSH_OPTIONS_IDENTITY: * - SSH_OPTIONS_IDENTITY:
* Get the first identity file name (const char *).\n * Get the first identity file name (const char *).\n
* \n * \n
* By default identity, id_dsa and id_rsa are checked. * By default id_rsa, id_ecdsa and id_ed25519 files are used.
* *
* - SSH_OPTIONS_PROXYCOMMAND: * - SSH_OPTIONS_PROXYCOMMAND:
* Get the proxycommand necessary to log into the * Get the proxycommand necessary to log into the
@@ -1260,7 +1270,11 @@ int ssh_options_get(ssh_session session, enum ssh_options_e type, char** value)
break; break;
} }
case SSH_OPTIONS_IDENTITY: { case SSH_OPTIONS_IDENTITY: {
struct ssh_iterator *it = ssh_list_get_iterator(session->opts.identity); struct ssh_iterator *it;
it = ssh_list_get_iterator(session->opts.identity);
if (it == NULL) {
it = ssh_list_get_iterator(session->opts.identity_non_exp);
}
if (it == NULL) { if (it == NULL) {
return SSH_ERROR; return SSH_ERROR;
} }
@@ -1555,7 +1569,6 @@ out:
int ssh_options_apply(ssh_session session) int ssh_options_apply(ssh_session session)
{ {
struct ssh_iterator *it;
char *tmp; char *tmp;
int rc; int rc;
@@ -1600,6 +1613,7 @@ int ssh_options_apply(ssh_session session)
size_t plen = strlen(session->opts.ProxyCommand) + size_t plen = strlen(session->opts.ProxyCommand) +
5 /* strlen("exec ") */; 5 /* strlen("exec ") */;
if (strncmp(session->opts.ProxyCommand, "exec ", 5) != 0) {
p = malloc(plen + 1 /* \0 */); p = malloc(plen + 1 /* \0 */);
if (p == NULL) { if (p == NULL) {
return -1; return -1;
@@ -1610,6 +1624,7 @@ int ssh_options_apply(ssh_session session)
free(p); free(p);
return -1; return -1;
} }
}
tmp = ssh_path_expand_escape(session, p); tmp = ssh_path_expand_escape(session, p);
free(p); free(p);
@@ -1620,25 +1635,34 @@ int ssh_options_apply(ssh_session session)
session->opts.ProxyCommand = tmp; session->opts.ProxyCommand = tmp;
} }
for (it = ssh_list_get_iterator(session->opts.identity); for (tmp = ssh_list_pop_head(char *, session->opts.identity_non_exp);
it != NULL; tmp != NULL;
it = it->next) { tmp = ssh_list_pop_head(char *, session->opts.identity_non_exp)) {
char *id = (char *) it->data; char *id = tmp;
if (strncmp(id, "pkcs11:", 6) == 0) { if (strncmp(id, "pkcs11:", 6) != 0) {
/* PKCS#11 URIs are using percent-encoding so we can not mix /* PKCS#11 URIs are using percent-encoding so we can not mix
* it with ssh expansion of ssh escape characters. * it with ssh expansion of ssh escape characters.
* Skip these identities now, before we will have PKCS#11 support
*/ */
continue;
}
tmp = ssh_path_expand_escape(session, id); tmp = ssh_path_expand_escape(session, id);
if (tmp == NULL) { if (tmp == NULL) {
return -1; return -1;
} }
free(id); free(id);
it->data = tmp;
} }
/* use append to keep the order at first call and use prepend
* to put anything that comes on the nth calls to the beginning */
if (session->opts.exp_flags & SSH_OPT_EXP_FLAG_IDENTITY) {
rc = ssh_list_prepend(session->opts.identity, tmp);
} else {
rc = ssh_list_append(session->opts.identity, tmp);
}
if (rc != SSH_OK) {
return -1;
}
}
session->opts.exp_flags |= SSH_OPT_EXP_FLAG_IDENTITY;
return 0; return 0;
} }

View File

@@ -119,13 +119,17 @@ ssh_session ssh_new(void)
if (session->opts.identity == NULL) { if (session->opts.identity == NULL) {
goto err; goto err;
} }
session->opts.identity_non_exp = ssh_list_new();
if (session->opts.identity_non_exp == NULL) {
goto err;
}
id = strdup("%d/id_ed25519"); id = strdup("%d/id_ed25519");
if (id == NULL) { if (id == NULL) {
goto err; goto err;
} }
rc = ssh_list_append(session->opts.identity, id); rc = ssh_list_append(session->opts.identity_non_exp, id);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
goto err; goto err;
} }
@@ -135,7 +139,7 @@ ssh_session ssh_new(void)
if (id == NULL) { if (id == NULL) {
goto err; goto err;
} }
rc = ssh_list_append(session->opts.identity, id); rc = ssh_list_append(session->opts.identity_non_exp, id);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
goto err; goto err;
} }
@@ -145,7 +149,7 @@ ssh_session ssh_new(void)
if (id == NULL) { if (id == NULL) {
goto err; goto err;
} }
rc = ssh_list_append(session->opts.identity, id); rc = ssh_list_append(session->opts.identity_non_exp, id);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
goto err; goto err;
} }
@@ -155,7 +159,7 @@ ssh_session ssh_new(void)
if (id == NULL) { if (id == NULL) {
goto err; goto err;
} }
rc = ssh_list_append(session->opts.identity, id); rc = ssh_list_append(session->opts.identity_non_exp, id);
if (rc == SSH_ERROR) { if (rc == SSH_ERROR) {
goto err; goto err;
} }
@@ -285,6 +289,17 @@ void ssh_free(ssh_session session)
ssh_list_free(session->opts.identity); ssh_list_free(session->opts.identity);
} }
if (session->opts.identity_non_exp) {
char *id;
for (id = ssh_list_pop_head(char *, session->opts.identity_non_exp);
id != NULL;
id = ssh_list_pop_head(char *, session->opts.identity_non_exp)) {
SAFE_FREE(id);
}
ssh_list_free(session->opts.identity_non_exp);
}
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) {
SSH_BUFFER_FREE(b); SSH_BUFFER_FREE(b);