1654 lines
62 KiB
Diff
1654 lines
62 KiB
Diff
From d1315bf155f5541e769bac58bdbb1cf343a70952 Mon Sep 17 00:00:00 2001
|
|
From: Norbert Pocs <npocs@redhat.com>
|
|
Date: Mon, 7 Nov 2022 13:08:02 +0100
|
|
Subject: [PATCH 1/6] tokens: Add low-level function to exlclude, prepend lists
|
|
|
|
These functions are needed for openssh -,^ features.
|
|
|
|
Signed-off-by: Norbert Pocs <npocs@redhat.com>
|
|
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
|
|
---
|
|
include/libssh/token.h | 8 +++
|
|
src/token.c | 141 +++++++++++++++++++++++++++++++++++++++--
|
|
2 files changed, 145 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/include/libssh/token.h b/include/libssh/token.h
|
|
index 9896fb06..2d07f8c4 100644
|
|
--- a/include/libssh/token.h
|
|
+++ b/include/libssh/token.h
|
|
@@ -45,4 +45,12 @@ char *ssh_remove_duplicates(const char *list);
|
|
|
|
char *ssh_append_without_duplicates(const char *list,
|
|
const char *appended_list);
|
|
+char *ssh_prefix_without_duplicates(const char *list,
|
|
+ const char *prefixed_list);
|
|
+char *ssh_remove_all_matching(const char *list,
|
|
+ const char *remove_list);
|
|
+
|
|
+#ifdef __cplusplus
|
|
+}
|
|
+#endif
|
|
#endif /* TOKEN_H_ */
|
|
diff --git a/src/token.c b/src/token.c
|
|
index 0924d3bd..58befe1d 100644
|
|
--- a/src/token.c
|
|
+++ b/src/token.c
|
|
@@ -376,6 +376,7 @@ char *ssh_append_without_duplicates(const char *list,
|
|
{
|
|
size_t concat_len = 0;
|
|
char *ret = NULL, *concat = NULL;
|
|
+ int rc = 0;
|
|
|
|
if (list != NULL) {
|
|
concat_len = strlen(list);
|
|
@@ -396,12 +397,144 @@ char *ssh_append_without_duplicates(const char *list,
|
|
return NULL;
|
|
}
|
|
|
|
+ rc = snprintf(concat, concat_len, "%s%s%s",
|
|
+ list == NULL ? "" : list,
|
|
+ list == NULL ? "" : ",",
|
|
+ appended_list == NULL ? "" : appended_list);
|
|
+ if (rc < 0) {
|
|
+ SAFE_FREE(concat);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ ret = ssh_remove_duplicates(concat);
|
|
+
|
|
+ SAFE_FREE(concat);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @internal
|
|
+ *
|
|
+ * @brief Given two strings containing lists of tokens, return a newly
|
|
+ * allocated string containing the elements of the first list without the
|
|
+ * elements of the second list. The order of the elements will be preserved.
|
|
+ *
|
|
+ * @param[in] list The first list
|
|
+ * @param[in] remove_list The list to be removed
|
|
+ *
|
|
+ * @return A newly allocated copy list containing elements of the
|
|
+ * list without the elements of remove_list; NULL in case of error.
|
|
+ */
|
|
+char *ssh_remove_all_matching(const char *list,
|
|
+ const char *remove_list)
|
|
+{
|
|
+ struct ssh_tokens_st *l_tok = NULL, *r_tok = NULL;
|
|
+ int i, j, cmp;
|
|
+ char *ret = NULL;
|
|
+ size_t len, pos = 0;
|
|
+ bool exclude;
|
|
+
|
|
+ if ((list == NULL)) {
|
|
+ return NULL;
|
|
+ }
|
|
+ if (remove_list == NULL) {
|
|
+ return strdup (list);
|
|
+ }
|
|
+
|
|
+ l_tok = ssh_tokenize(list, ',');
|
|
+ if (l_tok == NULL) {
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ r_tok = ssh_tokenize(remove_list, ',');
|
|
+ if (r_tok == NULL) {
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ ret = calloc(1, strlen(list) + 1);
|
|
+ if (ret == NULL) {
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ for (i = 0; l_tok->tokens[i]; i++) {
|
|
+ exclude = false;
|
|
+ for (j = 0; r_tok->tokens[j]; j++) {
|
|
+ cmp = strcmp(l_tok->tokens[i], r_tok->tokens[j]);
|
|
+ if (cmp == 0) {
|
|
+ exclude = true;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (exclude == false) {
|
|
+ if (pos != 0) {
|
|
+ ret[pos] = ',';
|
|
+ pos++;
|
|
+ }
|
|
+
|
|
+ len = strlen(l_tok->tokens[i]);
|
|
+ memcpy(&ret[pos], l_tok->tokens[i], len);
|
|
+ pos += len;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ret[0] == '\0') {
|
|
+ SAFE_FREE(ret);
|
|
+ }
|
|
+
|
|
+out:
|
|
+ ssh_tokens_free(l_tok);
|
|
+ ssh_tokens_free(r_tok);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @internal
|
|
+ *
|
|
+ * @brief Given two strings containing lists of tokens, return a newly
|
|
+ * allocated string containing all the elements of the first list prefixed at
|
|
+ * the beginning of the second list, without duplicates.
|
|
+ *
|
|
+ * @param[in] list The first list
|
|
+ * @param[in] prefixed_list The list to use as a prefix
|
|
+ *
|
|
+ * @return A newly allocated list containing all the elements
|
|
+ * of the list prefixed with the elements of the prefixed_list without
|
|
+ * duplicates; NULL in case of error.
|
|
+ */
|
|
+char *ssh_prefix_without_duplicates(const char *list,
|
|
+ const char *prefixed_list)
|
|
+{
|
|
+ size_t concat_len = 0;
|
|
+ char *ret = NULL, *concat = NULL;
|
|
+ int rc = 0;
|
|
+
|
|
if (list != NULL) {
|
|
- strcpy(concat, list);
|
|
- strncat(concat, ",", concat_len - strlen(concat) - 1);
|
|
+ concat_len = strlen(list);
|
|
}
|
|
- if (appended_list != NULL) {
|
|
- strncat(concat, appended_list, concat_len - strlen(concat) - 1);
|
|
+
|
|
+ if (prefixed_list != NULL) {
|
|
+ concat_len += strlen(prefixed_list);
|
|
+ }
|
|
+
|
|
+ if (concat_len == 0) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ /* Add room for ending '\0' and for middle ',' */
|
|
+ concat_len += 2;
|
|
+ concat = calloc(concat_len, 1);
|
|
+ if (concat == NULL) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ rc = snprintf(concat, concat_len, "%s%s%s",
|
|
+ prefixed_list == NULL ? "" : prefixed_list,
|
|
+ prefixed_list == NULL ? "" : ",",
|
|
+ list == NULL ? "" : list);
|
|
+ if (rc < 0) {
|
|
+ SAFE_FREE(concat);
|
|
+ return NULL;
|
|
}
|
|
|
|
ret = ssh_remove_duplicates(concat);
|
|
--
|
|
2.38.1
|
|
|
|
|
|
From f4516b9d43c4730ca5f60d73567596d65a672e16 Mon Sep 17 00:00:00 2001
|
|
From: Norbert Pocs <npocs@redhat.com>
|
|
Date: Fri, 11 Nov 2022 17:47:22 +0100
|
|
Subject: [PATCH 2/6] torture_tokens.c: Add tests for new token functions
|
|
|
|
Functions `ssh_remove_all_matching` and `ssh_prefix_without_duplicates` were
|
|
added; a little test suite will suite them.
|
|
|
|
Signed-off-by: Norbert Pocs <npocs@redhat.com>
|
|
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
|
|
---
|
|
tests/unittests/torture_tokens.c | 64 ++++++++++++++++++++++++++++++++
|
|
1 file changed, 64 insertions(+)
|
|
|
|
diff --git a/tests/unittests/torture_tokens.c b/tests/unittests/torture_tokens.c
|
|
index 6b52b847..438538de 100644
|
|
--- a/tests/unittests/torture_tokens.c
|
|
+++ b/tests/unittests/torture_tokens.c
|
|
@@ -265,6 +265,68 @@ static void torture_append_without_duplicate(UNUSED_PARAM(void **state))
|
|
}
|
|
}
|
|
|
|
+static void torture_remove_all_matching (UNUSED_PARAM(void** state)) {
|
|
+ char *p;
|
|
+
|
|
+ p = ssh_remove_all_matching(NULL, NULL);
|
|
+ assert_null(p);
|
|
+
|
|
+ p = ssh_remove_all_matching("don't remove", NULL);
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "don't remove");
|
|
+ free(p);
|
|
+
|
|
+ p = ssh_remove_all_matching("a,b,c", "b");
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "a,c");
|
|
+ free(p);
|
|
+
|
|
+ p = ssh_remove_all_matching("a,b,c", "a,b");
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "c");
|
|
+ free(p);
|
|
+
|
|
+ p = ssh_remove_all_matching("a,b,c", "d");
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "a,b,c");
|
|
+ free(p);
|
|
+
|
|
+ p = ssh_remove_all_matching("a,b,c", "a,b,c");
|
|
+ assert_null(p);
|
|
+}
|
|
+
|
|
+static void torture_prefix_without_duplicates (UNUSED_PARAM(void** state)) {
|
|
+ char *p;
|
|
+
|
|
+ p = ssh_prefix_without_duplicates(NULL, NULL);
|
|
+ assert_null(p);
|
|
+
|
|
+ p = ssh_prefix_without_duplicates("a,b,c", NULL);
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "a,b,c");
|
|
+ free(p);
|
|
+
|
|
+ p = ssh_prefix_without_duplicates("a,b,c", "a");
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "a,b,c");
|
|
+ free(p);
|
|
+
|
|
+ p = ssh_prefix_without_duplicates("a,b,c", "b");
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "b,a,c");
|
|
+ free(p);
|
|
+
|
|
+ p = ssh_prefix_without_duplicates("a,b,c", "x");
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "x,a,b,c");
|
|
+ free(p);
|
|
+
|
|
+ p = ssh_prefix_without_duplicates("a,b,c", "c,x");
|
|
+ assert_non_null(p);
|
|
+ assert_string_equal(p, "c,x,a,b");
|
|
+ free(p);
|
|
+}
|
|
+
|
|
|
|
int torture_run_tests(void)
|
|
{
|
|
@@ -275,6 +337,8 @@ int torture_run_tests(void)
|
|
cmocka_unit_test(torture_find_all_matching),
|
|
cmocka_unit_test(torture_remove_duplicate),
|
|
cmocka_unit_test(torture_append_without_duplicate),
|
|
+ cmocka_unit_test(torture_remove_all_matching),
|
|
+ cmocka_unit_test(torture_prefix_without_duplicates),
|
|
};
|
|
|
|
ssh_init();
|
|
--
|
|
2.38.1
|
|
|
|
|
|
From be50b4296574ba59537415b9903e8e4aa94cce53 Mon Sep 17 00:00:00 2001
|
|
From: Norbert Pocs <npocs@redhat.com>
|
|
Date: Mon, 7 Nov 2022 08:23:30 +0100
|
|
Subject: [PATCH 3/6] kex: Add functions for openssh +,-,^ features
|
|
|
|
The funcions can:
|
|
- add a list to the default list
|
|
- remove a list from the default list
|
|
- prepend a list to the default list
|
|
|
|
Signed-off-by: Norbert Pocs <npocs@redhat.com>
|
|
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
|
|
---
|
|
include/libssh/kex.h | 4 ++
|
|
src/kex.c | 105 +++++++++++++++++++++++++++++++++++++++++++
|
|
2 files changed, 109 insertions(+)
|
|
|
|
diff --git a/include/libssh/kex.h b/include/libssh/kex.h
|
|
index 3a1f4a6f..23b93924 100644
|
|
--- a/include/libssh/kex.h
|
|
+++ b/include/libssh/kex.h
|
|
@@ -40,6 +40,10 @@ int ssh_kex_select_methods(ssh_session session);
|
|
int ssh_verify_existing_algo(enum ssh_kex_types_e algo, const char *name);
|
|
char *ssh_keep_known_algos(enum ssh_kex_types_e algo, const char *list);
|
|
char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list);
|
|
+char *ssh_add_to_default_algos(enum ssh_kex_types_e algo, const char *list);
|
|
+char *ssh_remove_from_default_algos(enum ssh_kex_types_e algo,
|
|
+ const char *list);
|
|
+char *ssh_prefix_default_algos(enum ssh_kex_types_e algo, const char *list);
|
|
char **ssh_space_tokenize(const char *chain);
|
|
int ssh_get_kex1(ssh_session session);
|
|
char *ssh_find_matching(const char *in_d, const char *what_d);
|
|
diff --git a/src/kex.c b/src/kex.c
|
|
index 64083997..1155b9c7 100644
|
|
--- a/src/kex.c
|
|
+++ b/src/kex.c
|
|
@@ -983,6 +983,111 @@ char *ssh_keep_fips_algos(enum ssh_kex_types_e algo, const char *list)
|
|
return ssh_find_all_matching(fips_methods[algo], list);
|
|
}
|
|
|
|
+/**
|
|
+ * @internal
|
|
+ *
|
|
+ * @brief Return a newly allocated string containing the default
|
|
+ * algorithms plus the algorithms specified in list. If the system
|
|
+ * runs in fips mode, this will add only fips approved algorithms.
|
|
+ * Empty list will cause error.
|
|
+ *
|
|
+ * @param[in] algo The type of the methods to filter
|
|
+ * @param[in] list The list to be appended
|
|
+ *
|
|
+ * @return A newly allocated list containing the default algorithms and the
|
|
+ * algorithms in list at the end; NULL in case of error.
|
|
+ */
|
|
+char *ssh_add_to_default_algos(enum ssh_kex_types_e algo, const char *list)
|
|
+{
|
|
+ char *tmp = NULL, *ret = NULL;
|
|
+
|
|
+ if (algo > SSH_LANG_S_C || list == NULL || list[0] == '\0') {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ tmp = ssh_append_without_duplicates(fips_methods[algo], list);
|
|
+ ret = ssh_find_all_matching(fips_methods[algo], tmp);
|
|
+ } else {
|
|
+ tmp = ssh_append_without_duplicates(default_methods[algo], list);
|
|
+ ret = ssh_find_all_matching(supported_methods[algo], tmp);
|
|
+ }
|
|
+
|
|
+ free(tmp);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @internal
|
|
+ *
|
|
+ * @brief Return a newly allocated string containing the default
|
|
+ * algorithms excluding the algorithms specified in list. If the system
|
|
+ * runs in fips mode, this will remove from the fips_methods list.
|
|
+ *
|
|
+ * @param[in] algo The type of the methods to filter
|
|
+ * @param[in] list The list to be exclude
|
|
+ *
|
|
+ * @return A newly allocated list containing the default algorithms without the
|
|
+ * algorithms in list; NULL in case of error.
|
|
+ */
|
|
+char *ssh_remove_from_default_algos(enum ssh_kex_types_e algo, const char *list)
|
|
+{
|
|
+ if (algo > SSH_LANG_S_C) {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (list == NULL || list[0] == '\0') {
|
|
+ if (ssh_fips_mode()) {
|
|
+ return strdup(fips_methods[algo]);
|
|
+ } else {
|
|
+ return strdup(default_methods[algo]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ return ssh_remove_all_matching(fips_methods[algo], list);
|
|
+ } else {
|
|
+ return ssh_remove_all_matching(default_methods[algo], list);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @internal
|
|
+ *
|
|
+ * @brief Return a newly allocated string containing the default
|
|
+ * algorithms with prioritized algorithms specified in list. If the
|
|
+ * algorithms are present in the default list they get prioritized, if not
|
|
+ * they are added to the front of the default list. If the system
|
|
+ * runs in fips mode, this will work with the fips_methods list.
|
|
+ * Empty list will cause error.
|
|
+ *
|
|
+ * @param[in] algo The type of the methods to filter
|
|
+ * @param[in] list The list to be pushed to priority
|
|
+ *
|
|
+ * @return A newly allocated list containing the default algorithms prioritized
|
|
+ * with the algorithms in list at the beginning of the list; NULL in case
|
|
+ * of error.
|
|
+ */
|
|
+char *ssh_prefix_default_algos(enum ssh_kex_types_e algo, const char *list)
|
|
+{
|
|
+ char *ret = NULL, *tmp = NULL;
|
|
+
|
|
+ if (algo > SSH_LANG_S_C || list == NULL || list[0] == '\0') {
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ tmp = ssh_prefix_without_duplicates(fips_methods[algo], list);
|
|
+ ret = ssh_find_all_matching(fips_methods[algo], tmp);
|
|
+ } else {
|
|
+ tmp = ssh_prefix_without_duplicates(default_methods[algo], list);
|
|
+ ret = ssh_find_all_matching(supported_methods[algo], tmp);
|
|
+ }
|
|
+
|
|
+ free(tmp);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int ssh_make_sessionid(ssh_session session)
|
|
{
|
|
ssh_string num = NULL;
|
|
--
|
|
2.38.1
|
|
|
|
|
|
From 0d5d6e750a0c25700a47a760cb066b6027a54b09 Mon Sep 17 00:00:00 2001
|
|
From: Norbert Pocs <npocs@redhat.com>
|
|
Date: Mon, 7 Nov 2022 13:13:20 +0100
|
|
Subject: [PATCH 4/6] options.c: Add support for openssh config +,-,^
|
|
|
|
These features allow for options Ciphers, HostKeyAlgorithms, KexAlgorithms and
|
|
MACs to append, remove and prepend to the default list of algorithms
|
|
respectively
|
|
|
|
Signed-off-by: Norbert Pocs <npocs@redhat.com>
|
|
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
|
|
---
|
|
include/libssh/options.h | 3 +-
|
|
src/options.c | 244 +++++++++++++++++++++++++--------------
|
|
src/server.c | 3 +-
|
|
3 files changed, 161 insertions(+), 89 deletions(-)
|
|
|
|
diff --git a/include/libssh/options.h b/include/libssh/options.h
|
|
index e8dc6c69..dd04c8af 100644
|
|
--- a/include/libssh/options.h
|
|
+++ b/include/libssh/options.h
|
|
@@ -25,7 +25,8 @@ int ssh_config_parse_file(ssh_session session, const char *filename);
|
|
int ssh_config_parse_string(ssh_session session, const char *input);
|
|
int ssh_options_set_algo(ssh_session session,
|
|
enum ssh_kex_types_e algo,
|
|
- const char *list);
|
|
+ const char *list,
|
|
+ char **place);
|
|
int ssh_options_apply(ssh_session session);
|
|
|
|
#endif /* _OPTIONS_H */
|
|
diff --git a/src/options.c b/src/options.c
|
|
index 49aaefa2..56e09c65 100644
|
|
--- a/src/options.c
|
|
+++ b/src/options.c
|
|
@@ -221,14 +221,30 @@ int ssh_options_copy(ssh_session src, ssh_session *dest)
|
|
|
|
int ssh_options_set_algo(ssh_session session,
|
|
enum ssh_kex_types_e algo,
|
|
- const char *list)
|
|
+ const char *list,
|
|
+ char **place)
|
|
{
|
|
- char *p = NULL;
|
|
+ /* When the list start with +,-,^ the filtration of unknown algorithms
|
|
+ * gets handled inside the helper functions, otherwise the list is taken
|
|
+ * as it is. */
|
|
+ char *p = (char *)list;
|
|
+
|
|
+ if (algo < SSH_COMP_C_S) {
|
|
+ if (list[0] == '+') {
|
|
+ p = ssh_add_to_default_algos(algo, list+1);
|
|
+ } else if (list[0] == '-') {
|
|
+ p = ssh_remove_from_default_algos(algo, list+1);
|
|
+ } else if (list[0] == '^') {
|
|
+ p = ssh_prefix_default_algos(algo, list+1);
|
|
+ }
|
|
+ }
|
|
|
|
- if (ssh_fips_mode()) {
|
|
- p = ssh_keep_fips_algos(algo, list);
|
|
- } else {
|
|
- p = ssh_keep_known_algos(algo, list);
|
|
+ if (p == list) {
|
|
+ if (ssh_fips_mode()) {
|
|
+ p = ssh_keep_fips_algos(algo, list);
|
|
+ } else {
|
|
+ p = ssh_keep_known_algos(algo, list);
|
|
+ }
|
|
}
|
|
|
|
if (p == NULL) {
|
|
@@ -238,8 +254,8 @@ int ssh_options_set_algo(ssh_session session,
|
|
return -1;
|
|
}
|
|
|
|
- SAFE_FREE(session->opts.wanted_methods[algo]);
|
|
- session->opts.wanted_methods[algo] = p;
|
|
+ SAFE_FREE(*place);
|
|
+ *place = p;
|
|
|
|
return 0;
|
|
}
|
|
@@ -356,34 +372,60 @@ int ssh_options_set_algo(ssh_session session,
|
|
*
|
|
* - SSH_OPTIONS_CIPHERS_C_S:
|
|
* Set the symmetric cipher client to server (const char *,
|
|
- * comma-separated list).
|
|
+ * comma-separated list). The list can be prepended by +,-,^
|
|
+ * which can append, remove or move to the beginning
|
|
+ * (prioritizing) of the default list respectively. Giving an
|
|
+ * empty list after + and ^ will cause error.
|
|
*
|
|
* - SSH_OPTIONS_CIPHERS_S_C:
|
|
* Set the symmetric cipher server to client (const char *,
|
|
- * comma-separated list).
|
|
+ * comma-separated list). The list can be prepended by +,-,^
|
|
+ * which can append, remove or move to the beginning
|
|
+ * (prioritizing) of the default list respectively. Giving an
|
|
+ * empty list after + and ^ will cause error.
|
|
*
|
|
* - SSH_OPTIONS_KEY_EXCHANGE:
|
|
* Set the key exchange method to be used (const char *,
|
|
* comma-separated list). ex:
|
|
* "ecdh-sha2-nistp256,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"
|
|
+ * The list can be prepended by +,-,^ which will append,
|
|
+ * remove or move to the beginning (prioritizing) of the
|
|
+ * default list respectively. Giving an empty list
|
|
+ * after + and ^ will cause error.
|
|
*
|
|
* - SSH_OPTIONS_HMAC_C_S:
|
|
* Set the Message Authentication Code algorithm client to server
|
|
- * (const char *, comma-separated list).
|
|
+ * (const char *, comma-separated list). The list can be
|
|
+ * prepended by +,-,^ which will append, remove or move to
|
|
+ * the beginning (prioritizing) of the default list
|
|
+ * respectively. Giving an empty list after + and ^ will
|
|
+ * cause error.
|
|
*
|
|
* - SSH_OPTIONS_HMAC_S_C:
|
|
* Set the Message Authentication Code algorithm server to client
|
|
- * (const char *, comma-separated list).
|
|
+ * (const char *, comma-separated list). The list can be
|
|
+ * prepended by +,-,^ which will append, remove or move to
|
|
+ * the beginning (prioritizing) of the default list
|
|
+ * respectively. Giving an empty list after + and ^ will
|
|
+ * cause error.
|
|
*
|
|
* - SSH_OPTIONS_HOSTKEYS:
|
|
* Set the preferred server host key types (const char *,
|
|
* comma-separated list). ex:
|
|
- * "ssh-rsa,ssh-dss,ecdh-sha2-nistp256"
|
|
+ * "ssh-rsa,ssh-dss,ecdh-sha2-nistp256". The list can be
|
|
+ * prepended by +,-,^ which will append, remove or move to
|
|
+ * the beginning (prioritizing) of the default list
|
|
+ * respectively. Giving an empty list after + and ^ will
|
|
+ * cause error.
|
|
*
|
|
* - SSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES:
|
|
* Set the preferred public key algorithms to be used for
|
|
* authentication (const char *, comma-separated list). ex:
|
|
* "ssh-rsa,rsa-sha2-256,ssh-dss,ecdh-sha2-nistp256"
|
|
+ * The list can be prepended by +,-,^ which will append,
|
|
+ * remove or move to the beginning (prioritizing) of the
|
|
+ * default list respectively. Giving an empty list
|
|
+ * after + and ^ will cause error.
|
|
*
|
|
* - SSH_OPTIONS_COMPRESSION_C_S:
|
|
* Set the compression to use for client to server
|
|
@@ -496,6 +538,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
long int i;
|
|
unsigned int u;
|
|
int rc;
|
|
+ char **wanted_methods = session->opts.wanted_methods;
|
|
|
|
if (session == NULL) {
|
|
return -1;
|
|
@@ -779,7 +822,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_options_set_algo(session, SSH_CRYPT_C_S, v) < 0)
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_CRYPT_C_S,
|
|
+ v,
|
|
+ &wanted_methods[SSH_CRYPT_C_S]);
|
|
+ if (rc < 0)
|
|
return -1;
|
|
}
|
|
break;
|
|
@@ -789,7 +836,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_options_set_algo(session, SSH_CRYPT_S_C, v) < 0)
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_CRYPT_S_C,
|
|
+ v,
|
|
+ &wanted_methods[SSH_CRYPT_S_C]);
|
|
+ if (rc < 0)
|
|
return -1;
|
|
}
|
|
break;
|
|
@@ -799,7 +850,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_options_set_algo(session, SSH_KEX, v) < 0)
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_KEX,
|
|
+ v,
|
|
+ &wanted_methods[SSH_KEX]);
|
|
+ if (rc < 0)
|
|
return -1;
|
|
}
|
|
break;
|
|
@@ -809,7 +864,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_options_set_algo(session, SSH_HOSTKEYS, v) < 0)
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_HOSTKEYS,
|
|
+ v,
|
|
+ &wanted_methods[SSH_HOSTKEYS]);
|
|
+ if (rc < 0)
|
|
return -1;
|
|
}
|
|
break;
|
|
@@ -819,20 +878,12 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_fips_mode()) {
|
|
- p = ssh_keep_fips_algos(SSH_HOSTKEYS, v);
|
|
- } else {
|
|
- p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
|
|
- }
|
|
- if (p == NULL) {
|
|
- ssh_set_error(session, SSH_REQUEST_DENIED,
|
|
- "Setting method: no known public key algorithm (%s)",
|
|
- v);
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_HOSTKEYS,
|
|
+ v,
|
|
+ &session->opts.pubkey_accepted_types);
|
|
+ if (rc < 0)
|
|
return -1;
|
|
- }
|
|
-
|
|
- SAFE_FREE(session->opts.pubkey_accepted_types);
|
|
- session->opts.pubkey_accepted_types = p;
|
|
}
|
|
break;
|
|
case SSH_OPTIONS_HMAC_C_S:
|
|
@@ -841,7 +892,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_options_set_algo(session, SSH_MAC_C_S, v) < 0)
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_MAC_C_S,
|
|
+ v,
|
|
+ &wanted_methods[SSH_MAC_C_S]);
|
|
+ if (rc < 0)
|
|
return -1;
|
|
}
|
|
break;
|
|
@@ -851,7 +906,11 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_options_set_algo(session, SSH_MAC_S_C, v) < 0)
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_MAC_S_C,
|
|
+ v,
|
|
+ &wanted_methods[SSH_MAC_S_C]);
|
|
+ if (rc < 0)
|
|
return -1;
|
|
}
|
|
break;
|
|
@@ -861,16 +920,18 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (strcasecmp(value,"yes")==0){
|
|
- if(ssh_options_set_algo(session,SSH_COMP_C_S,"zlib@openssh.com,zlib,none") < 0)
|
|
- return -1;
|
|
- } else if (strcasecmp(value,"no")==0){
|
|
- if(ssh_options_set_algo(session,SSH_COMP_C_S,"none,zlib@openssh.com,zlib") < 0)
|
|
- return -1;
|
|
- } else {
|
|
- if (ssh_options_set_algo(session, SSH_COMP_C_S, v) < 0)
|
|
- return -1;
|
|
+ const char *tmp = v;
|
|
+ if (strcasecmp(value, "yes") == 0){
|
|
+ tmp = "zlib@openssh.com,zlib,none";
|
|
+ } else if (strcasecmp(value, "no") == 0){
|
|
+ tmp = "none,zlib@openssh.com,zlib";
|
|
}
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_COMP_C_S,
|
|
+ tmp,
|
|
+ &wanted_methods[SSH_COMP_C_S]);
|
|
+ if (rc < 0)
|
|
+ return -1;
|
|
}
|
|
break;
|
|
case SSH_OPTIONS_COMPRESSION_S_C:
|
|
@@ -879,16 +940,19 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type,
|
|
ssh_set_error_invalid(session);
|
|
return -1;
|
|
} else {
|
|
- if (strcasecmp(value,"yes")==0){
|
|
- if(ssh_options_set_algo(session,SSH_COMP_S_C,"zlib@openssh.com,zlib,none") < 0)
|
|
- return -1;
|
|
- } else if (strcasecmp(value,"no")==0){
|
|
- if(ssh_options_set_algo(session,SSH_COMP_S_C,"none,zlib@openssh.com,zlib") < 0)
|
|
- return -1;
|
|
- } else {
|
|
- if (ssh_options_set_algo(session, SSH_COMP_S_C, v) < 0)
|
|
- return -1;
|
|
+ const char *tmp = v;
|
|
+ if (strcasecmp(value, "yes") == 0){
|
|
+ tmp = "zlib@openssh.com,zlib,none";
|
|
+ } else if (strcasecmp(value, "no") == 0){
|
|
+ tmp = "none,zlib@openssh.com,zlib";
|
|
}
|
|
+
|
|
+ rc = ssh_options_set_algo(session,
|
|
+ SSH_COMP_S_C,
|
|
+ tmp,
|
|
+ &wanted_methods[SSH_COMP_S_C]);
|
|
+ if (rc < 0)
|
|
+ return -1;
|
|
}
|
|
break;
|
|
case SSH_OPTIONS_COMPRESSION:
|
|
@@ -1604,26 +1668,12 @@ ssh_bind_set_key(ssh_bind sshbind, char **key_loc, const void *value)
|
|
|
|
static int ssh_bind_set_algo(ssh_bind sshbind,
|
|
enum ssh_kex_types_e algo,
|
|
- const char *list)
|
|
+ const char *list,
|
|
+ char **place)
|
|
{
|
|
- char *p = NULL;
|
|
-
|
|
- if (ssh_fips_mode()) {
|
|
- p = ssh_keep_fips_algos(algo, list);
|
|
- } else {
|
|
- p = ssh_keep_known_algos(algo, list);
|
|
- }
|
|
- if (p == NULL) {
|
|
- ssh_set_error(sshbind, SSH_REQUEST_DENIED,
|
|
- "Setting method: no algorithm for method \"%s\" (%s)",
|
|
- ssh_kex_get_description(algo), list);
|
|
- return -1;
|
|
- }
|
|
-
|
|
- SAFE_FREE(sshbind->wanted_methods[algo]);
|
|
- sshbind->wanted_methods[algo] = p;
|
|
-
|
|
- return 0;
|
|
+ /* sshbind is needed only for ssh_set_error which takes void*
|
|
+ * the typecast is only to satisfy function parameter type */
|
|
+ return ssh_options_set_algo((ssh_session)sshbind, algo, list, place);
|
|
}
|
|
|
|
/**
|
|
@@ -1765,6 +1815,7 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|
char *p, *q;
|
|
const char *v;
|
|
int i, rc;
|
|
+ char **wanted_methods = sshbind->wanted_methods;
|
|
|
|
if (sshbind == NULL) {
|
|
return -1;
|
|
@@ -2014,8 +2065,13 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|
ssh_set_error_invalid(sshbind);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_bind_set_algo(sshbind, SSH_CRYPT_C_S, v) < 0)
|
|
+ rc = ssh_bind_set_algo(sshbind,
|
|
+ SSH_CRYPT_C_S,
|
|
+ v,
|
|
+ &wanted_methods[SSH_CRYPT_C_S]);
|
|
+ if (rc < 0) {
|
|
return -1;
|
|
+ }
|
|
}
|
|
break;
|
|
case SSH_BIND_OPTIONS_CIPHERS_S_C:
|
|
@@ -2024,8 +2080,13 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|
ssh_set_error_invalid(sshbind);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_bind_set_algo(sshbind, SSH_CRYPT_S_C, v) < 0)
|
|
+ rc = ssh_bind_set_algo(sshbind,
|
|
+ SSH_CRYPT_S_C,
|
|
+ v,
|
|
+ &wanted_methods[SSH_CRYPT_S_C]);
|
|
+ if (rc < 0) {
|
|
return -1;
|
|
+ }
|
|
}
|
|
break;
|
|
case SSH_BIND_OPTIONS_KEY_EXCHANGE:
|
|
@@ -2034,7 +2095,10 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|
ssh_set_error_invalid(sshbind);
|
|
return -1;
|
|
} else {
|
|
- rc = ssh_bind_set_algo(sshbind, SSH_KEX, v);
|
|
+ rc = ssh_bind_set_algo(sshbind,
|
|
+ SSH_KEX,
|
|
+ v,
|
|
+ &wanted_methods[SSH_KEX]);
|
|
if (rc < 0) {
|
|
return -1;
|
|
}
|
|
@@ -2046,8 +2110,13 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|
ssh_set_error_invalid(sshbind);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_bind_set_algo(sshbind, SSH_MAC_C_S, v) < 0)
|
|
+ rc = ssh_bind_set_algo(sshbind,
|
|
+ SSH_MAC_C_S,
|
|
+ v,
|
|
+ &wanted_methods[SSH_MAC_C_S]);
|
|
+ if (rc < 0) {
|
|
return -1;
|
|
+ }
|
|
}
|
|
break;
|
|
case SSH_BIND_OPTIONS_HMAC_S_C:
|
|
@@ -2056,8 +2125,13 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|
ssh_set_error_invalid(sshbind);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_bind_set_algo(sshbind, SSH_MAC_S_C, v) < 0)
|
|
+ rc = ssh_bind_set_algo(sshbind,
|
|
+ SSH_MAC_S_C,
|
|
+ v,
|
|
+ &wanted_methods[SSH_MAC_S_C]);
|
|
+ if (rc < 0) {
|
|
return -1;
|
|
+ }
|
|
}
|
|
break;
|
|
case SSH_BIND_OPTIONS_CONFIG_DIR:
|
|
@@ -2082,20 +2156,13 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|
ssh_set_error_invalid(sshbind);
|
|
return -1;
|
|
} else {
|
|
- if (ssh_fips_mode()) {
|
|
- p = ssh_keep_fips_algos(SSH_HOSTKEYS, v);
|
|
- } else {
|
|
- p = ssh_keep_known_algos(SSH_HOSTKEYS, v);
|
|
- }
|
|
- if (p == NULL) {
|
|
- ssh_set_error(sshbind, SSH_REQUEST_DENIED,
|
|
- "Setting method: no known public key algorithm (%s)",
|
|
- v);
|
|
+ rc = ssh_bind_set_algo(sshbind,
|
|
+ SSH_HOSTKEYS,
|
|
+ v,
|
|
+ &sshbind->pubkey_accepted_key_types);
|
|
+ if (rc < 0) {
|
|
return -1;
|
|
}
|
|
-
|
|
- SAFE_FREE(sshbind->pubkey_accepted_key_types);
|
|
- sshbind->pubkey_accepted_key_types = p;
|
|
}
|
|
break;
|
|
case SSH_BIND_OPTIONS_HOSTKEY_ALGORITHMS:
|
|
@@ -2104,7 +2171,10 @@ int ssh_bind_options_set(ssh_bind sshbind, enum ssh_bind_options_e type,
|
|
ssh_set_error_invalid(sshbind);
|
|
return -1;
|
|
} else {
|
|
- rc = ssh_bind_set_algo(sshbind, SSH_HOSTKEYS, v);
|
|
+ rc = ssh_bind_set_algo(sshbind,
|
|
+ SSH_HOSTKEYS,
|
|
+ v,
|
|
+ &wanted_methods[SSH_HOSTKEYS]);
|
|
if (rc < 0) {
|
|
return -1;
|
|
}
|
|
diff --git a/src/server.c b/src/server.c
|
|
index 3fc25bd9..1b423fd0 100644
|
|
--- a/src/server.c
|
|
+++ b/src/server.c
|
|
@@ -160,7 +160,8 @@ int server_set_kex(ssh_session session)
|
|
|
|
rc = ssh_options_set_algo(session,
|
|
SSH_HOSTKEYS,
|
|
- kept);
|
|
+ kept,
|
|
+ &session->opts.wanted_methods[SSH_HOSTKEYS]);
|
|
SAFE_FREE(kept);
|
|
if (rc < 0) {
|
|
return -1;
|
|
--
|
|
2.38.1
|
|
|
|
|
|
From b6cc8f643624231a583bd7972e9503b3fa434caa Mon Sep 17 00:00:00 2001
|
|
From: Norbert Pocs <npocs@redhat.com>
|
|
Date: Mon, 7 Nov 2022 08:28:31 +0100
|
|
Subject: [PATCH 5/6] torture_options.c: Add test for config +,-,^ feature
|
|
|
|
Signed-off-by: Norbert Pocs <npocs@redhat.com>
|
|
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
|
|
---
|
|
tests/unittests/torture_options.c | 223 ++++++++++++++++++++++++++++++
|
|
1 file changed, 223 insertions(+)
|
|
|
|
diff --git a/tests/unittests/torture_options.c b/tests/unittests/torture_options.c
|
|
index e1d16f02..dc4df383 100644
|
|
--- a/tests/unittests/torture_options.c
|
|
+++ b/tests/unittests/torture_options.c
|
|
@@ -1087,6 +1087,223 @@ static void torture_options_getopt(void **state)
|
|
#endif /* _NSC_VER */
|
|
}
|
|
|
|
+static void torture_options_plus_sign(void **state)
|
|
+{
|
|
+ ssh_session session = *state;
|
|
+ int rc;
|
|
+ const char *def_host_alg, *alg, *algs;
|
|
+ char *awaited;
|
|
+ size_t alg_len, algs_len;
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ alg = ",rsa-sha2-512-cert-v01@openssh.com";
|
|
+ algs = ",rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ecdsa-sha2-nistp521";
|
|
+ def_host_alg = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
|
+ } else {
|
|
+ alg = ",ssh-rsa";
|
|
+ algs = ",ssh-rsa,ssh-rsa-cert-v01@openssh.com";
|
|
+ def_host_alg = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
|
+ }
|
|
+ alg_len = strlen(alg);
|
|
+ algs_len = strlen(algs);
|
|
+
|
|
+ /* in fips mode, the default list is the available list, which means
|
|
+ * we can't append anything because everything enabled is already
|
|
+ * included */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = strdup(def_host_alg);
|
|
+ assert_non_null(awaited);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_host_alg) + alg_len + 1, 1);
|
|
+ assert_non_null(awaited);
|
|
+
|
|
+ memcpy(awaited, def_host_alg, strlen(def_host_alg));
|
|
+ memcpy(awaited+strlen(def_host_alg), alg, alg_len);
|
|
+ }
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "+rsa-sha2-512-cert-v01@openssh.com");
|
|
+ } else {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "+ssh-rsa");
|
|
+ }
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ awaited);
|
|
+
|
|
+ if (!ssh_fips_mode()) {
|
|
+ /* different algorithm list is used here */
|
|
+ free(awaited);
|
|
+
|
|
+ awaited = calloc(strlen(def_host_alg) + algs_len + 1, 1);
|
|
+ assert_non_null(awaited);
|
|
+ memcpy(awaited, def_host_alg, strlen(def_host_alg));
|
|
+ memcpy(awaited+strlen(def_host_alg), algs, algs_len);
|
|
+ }
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS,
|
|
+ "+rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ecdsa-sha2-nistp521");
|
|
+ } else {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS,
|
|
+ "+ssh-rsa,ssh-rsa-cert-v01@openssh.com");
|
|
+ }
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ awaited);
|
|
+
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "+");
|
|
+ assert_ssh_return_code_equal(session, rc, SSH_ERROR);
|
|
+
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "+blablabla");
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ def_host_alg);
|
|
+
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, NULL);
|
|
+ assert_ssh_return_code_equal(session, rc, SSH_ERROR);
|
|
+
|
|
+ free(awaited);
|
|
+}
|
|
+
|
|
+static void torture_options_minus_sign(void **state)
|
|
+{
|
|
+ ssh_session session = *state;
|
|
+ int rc;
|
|
+ const char *def_host_alg, *alg, *algs;
|
|
+ char *awaited, *p;
|
|
+ size_t alg_len, algs_len;
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ alg = "rsa-sha2-512-cert-v01@openssh.com,";
|
|
+ algs = "rsa-sha2-256-cert-v01@openssh.com,ecdsa-sha2-nistp521,";
|
|
+ def_host_alg = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
|
+ } else {
|
|
+ alg = "ssh-ed25519,";
|
|
+ algs = "ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,";
|
|
+ def_host_alg = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
|
+ }
|
|
+ alg_len = strlen(alg);
|
|
+ algs_len = strlen(algs);
|
|
+
|
|
+ awaited = calloc(strlen(def_host_alg) + 1, 1);
|
|
+ assert_non_null(awaited);
|
|
+
|
|
+ memcpy(awaited, def_host_alg, strlen(def_host_alg));
|
|
+ p = strstr(awaited, alg);
|
|
+ assert_non_null(p);
|
|
+ memmove(p, p+alg_len, strlen(p + alg_len) + 1);
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "-rsa-sha2-512-cert-v01@openssh.com");
|
|
+ } else {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "-ssh-ed25519");
|
|
+ }
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ awaited);
|
|
+
|
|
+ p = strstr(awaited, algs);
|
|
+ assert_non_null(p);
|
|
+ memmove(p, p+algs_len, strlen(p + algs_len) + 1);
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "-rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ecdsa-sha2-nistp521");
|
|
+ } else {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "-ssh-ed25519,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384");
|
|
+ }
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ awaited);
|
|
+
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "-");
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ def_host_alg);
|
|
+
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "-blablabla");
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ def_host_alg);
|
|
+
|
|
+ free(awaited);
|
|
+}
|
|
+
|
|
+static void torture_options_caret_sign(void **state)
|
|
+{
|
|
+ ssh_session session = *state;
|
|
+ int rc;
|
|
+ const char *def_host_alg, *alg, *algs;
|
|
+ size_t alg_len, algs_len;
|
|
+ char *awaited, *p;
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ alg = "rsa-sha2-512-cert-v01@openssh.com,";
|
|
+ algs = "rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ecdsa-sha2-nistp521,";
|
|
+ def_host_alg = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
|
+ } else {
|
|
+ alg = "ssh-rsa,";
|
|
+ algs = "ssh-rsa,ssh-rsa-cert-v01@openssh.com,";
|
|
+ def_host_alg = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
|
+ }
|
|
+ alg_len = strlen(alg);
|
|
+ algs_len = strlen(algs);
|
|
+
|
|
+ awaited = calloc(strlen(def_host_alg) + alg_len + 1, 1);
|
|
+ assert_non_null(awaited);
|
|
+
|
|
+ memcpy(awaited, alg, alg_len);
|
|
+ memcpy(awaited+alg_len, def_host_alg, strlen(def_host_alg));
|
|
+ if (ssh_fips_mode()) {
|
|
+ p = strstr(awaited, alg);
|
|
+ /* look for second occurrence */
|
|
+ p = strstr(p+1, algs);
|
|
+ memmove(p, p+alg_len, strlen(p + alg_len) + 1);
|
|
+ }
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "^rsa-sha2-512-cert-v01@openssh.com");
|
|
+ } else {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "^ssh-rsa");
|
|
+ }
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ awaited);
|
|
+ /* different algorithm list is used here */
|
|
+ free(awaited);
|
|
+
|
|
+ awaited = calloc(strlen(def_host_alg) + algs_len + 1, 1);
|
|
+ assert_non_null(awaited);
|
|
+ memcpy(awaited, algs, algs_len);
|
|
+ memcpy(awaited+algs_len, def_host_alg, strlen(def_host_alg));
|
|
+ if (ssh_fips_mode()) {
|
|
+ p = strstr(awaited, algs);
|
|
+ /* look for second occurrence */
|
|
+ p = strstr(p+1, algs);
|
|
+ memmove(p, p+algs_len, strlen(p + algs_len) + 1);
|
|
+ }
|
|
+
|
|
+ if (ssh_fips_mode()) {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS,
|
|
+ "^rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ecdsa-sha2-nistp521");
|
|
+ } else {
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS,
|
|
+ "^ssh-rsa,ssh-rsa-cert-v01@openssh.com");
|
|
+ }
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ awaited);
|
|
+
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "^");
|
|
+ assert_ssh_return_code_equal(session, rc, SSH_ERROR);
|
|
+
|
|
+ rc = ssh_options_set(session, SSH_OPTIONS_HOSTKEYS, "^blablabla");
|
|
+ assert_ssh_return_code(session, rc);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS],
|
|
+ def_host_alg);
|
|
+
|
|
+ free(awaited);
|
|
+}
|
|
+
|
|
#ifdef WITH_SERVER
|
|
const char template[] = "temp_dir_XXXXXX";
|
|
|
|
@@ -1881,6 +2098,12 @@ int torture_run_tests(void) {
|
|
setup, teardown),
|
|
cmocka_unit_test_setup_teardown(torture_options_getopt,
|
|
setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_options_plus_sign,
|
|
+ setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_options_minus_sign,
|
|
+ setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_options_caret_sign,
|
|
+ setup, teardown),
|
|
};
|
|
|
|
#ifdef WITH_SERVER
|
|
--
|
|
2.38.1
|
|
|
|
|
|
From c73996c4e747a9e28f919d660411c804bc748324 Mon Sep 17 00:00:00 2001
|
|
From: Norbert Pocs <npocs@redhat.com>
|
|
Date: Thu, 10 Nov 2022 10:50:52 +0100
|
|
Subject: [PATCH 6/6] torture_config.c: Add test for +,-,^ config feature
|
|
|
|
It should be possible to use features to add,remove,prioritize
|
|
algorithms in the algorithm list from the config file.
|
|
|
|
Signed-off-by: Norbert Pocs <npocs@redhat.com>
|
|
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
|
|
---
|
|
tests/unittests/torture_config.c | 393 +++++++++++++++++++++++++++++++
|
|
1 file changed, 393 insertions(+)
|
|
|
|
diff --git a/tests/unittests/torture_config.c b/tests/unittests/torture_config.c
|
|
index 31dadae3..354adc2f 100644
|
|
--- a/tests/unittests/torture_config.c
|
|
+++ b/tests/unittests/torture_config.c
|
|
@@ -40,6 +40,9 @@ extern LIBSSH_THREAD int ssh_log_level;
|
|
#define LIBSSH_TESTCONFIG10 "libssh_testconfig10.tmp"
|
|
#define LIBSSH_TESTCONFIG11 "libssh_testconfig11.tmp"
|
|
#define LIBSSH_TESTCONFIG12 "libssh_testconfig12.tmp"
|
|
+#define LIBSSH_TESTCONFIG14 "libssh_testconfig14.tmp"
|
|
+#define LIBSSH_TESTCONFIG15 "libssh_testconfig15.tmp"
|
|
+#define LIBSSH_TESTCONFIG16 "libssh_testconfig16.tmp"
|
|
#define LIBSSH_TESTCONFIGGLOB "libssh_testc*[36].tmp"
|
|
#define LIBSSH_TEST_PUBKEYTYPES "libssh_test_PubkeyAcceptedKeyTypes.tmp"
|
|
#define LIBSSH_TEST_PUBKEYALGORITHMS "libssh_test_PubkeyAcceptedAlgorithms.tmp"
|
|
@@ -181,6 +184,27 @@ extern LIBSSH_THREAD int ssh_log_level;
|
|
"IdentityFile id_rsa_one\n" \
|
|
"IdentityFile id_ecdsa_two\n"
|
|
|
|
+/* +,-,^ features for all supported list */
|
|
+/* kex won't work in fips */
|
|
+#define LIBSSH_TESTCONFIG_STRING14 \
|
|
+ "HostKeyAlgorithms +ssh-rsa\n" \
|
|
+ "Ciphers +aes128-cbc,aes256-cbc\n" \
|
|
+ "KexAlgorithms +diffie-hellman-group14-sha1,diffie-hellman-group1-sha1\n" \
|
|
+ "MACs +hmac-sha1,hmac-sha1-etm@openssh.com\n"
|
|
+
|
|
+/* have to be algorithms which are in the default list */
|
|
+#define LIBSSH_TESTCONFIG_STRING15 \
|
|
+ "HostKeyAlgorithms -rsa-sha2-512,rsa-sha2-256\n" \
|
|
+ "Ciphers -aes256-ctr\n" \
|
|
+ "KexAlgorithms -diffie-hellman-group18-sha512,diffie-hellman-group16-sha512\n" \
|
|
+ "MACs -hmac-sha2-256-etm@openssh.com\n"
|
|
+
|
|
+#define LIBSSH_TESTCONFIG_STRING16 \
|
|
+ "HostKeyAlgorithms ^rsa-sha2-512,rsa-sha2-256\n" \
|
|
+ "Ciphers ^aes256-cbc\n" \
|
|
+ "KexAlgorithms ^diffie-hellman-group18-sha512,diffie-hellman-group16-sha512\n" \
|
|
+ "MACs ^hmac-sha1\n"
|
|
+
|
|
#define LIBSSH_TEST_PUBKEYTYPES_STRING \
|
|
"PubkeyAcceptedKeyTypes "PUBKEYACCEPTEDTYPES"\n"
|
|
|
|
@@ -238,6 +262,9 @@ static int setup_config_files(void **state)
|
|
unlink(LIBSSH_TESTCONFIG10);
|
|
unlink(LIBSSH_TESTCONFIG11);
|
|
unlink(LIBSSH_TESTCONFIG12);
|
|
+ unlink(LIBSSH_TESTCONFIG14);
|
|
+ unlink(LIBSSH_TESTCONFIG15);
|
|
+ unlink(LIBSSH_TESTCONFIG16);
|
|
unlink(LIBSSH_TEST_PUBKEYTYPES);
|
|
unlink(LIBSSH_TEST_PUBKEYALGORITHMS);
|
|
unlink(LIBSSH_TEST_NONEWLINEEND);
|
|
@@ -285,6 +312,14 @@ static int setup_config_files(void **state)
|
|
torture_write_file(LIBSSH_TESTCONFIG12,
|
|
LIBSSH_TESTCONFIG_STRING12);
|
|
|
|
+ /* +,-,^ feature */
|
|
+ torture_write_file(LIBSSH_TESTCONFIG14,
|
|
+ LIBSSH_TESTCONFIG_STRING14);
|
|
+ torture_write_file(LIBSSH_TESTCONFIG15,
|
|
+ LIBSSH_TESTCONFIG_STRING15);
|
|
+ torture_write_file(LIBSSH_TESTCONFIG16,
|
|
+ LIBSSH_TESTCONFIG_STRING16);
|
|
+
|
|
torture_write_file(LIBSSH_TEST_PUBKEYTYPES,
|
|
LIBSSH_TEST_PUBKEYTYPES_STRING);
|
|
|
|
@@ -316,6 +351,9 @@ static int teardown_config_files(void **state)
|
|
unlink(LIBSSH_TESTCONFIG10);
|
|
unlink(LIBSSH_TESTCONFIG11);
|
|
unlink(LIBSSH_TESTCONFIG12);
|
|
+ unlink(LIBSSH_TESTCONFIG14);
|
|
+ unlink(LIBSSH_TESTCONFIG15);
|
|
+ unlink(LIBSSH_TESTCONFIG16);
|
|
unlink(LIBSSH_TEST_PUBKEYTYPES);
|
|
unlink(LIBSSH_TEST_PUBKEYALGORITHMS);
|
|
|
|
@@ -1267,6 +1305,349 @@ static void torture_config_rekey_string(void **state)
|
|
torture_config_rekey(state, NULL, LIBSSH_TESTCONFIG_STRING12);
|
|
}
|
|
|
|
+/**
|
|
+ * @brief Remove substring from a string
|
|
+ *
|
|
+ * @param occurrence 0 means "remove the first occurrence"
|
|
+ * 1 means "remove the second occurrence" and so on
|
|
+ */
|
|
+static void helper_remove_substring(char *s, const char *subs, int occurrence) {
|
|
+ char *p;
|
|
+ /* remove the substring from the defaults */
|
|
+ p = strstr(s, subs);
|
|
+ assert_non_null(p);
|
|
+ /* look for second occurrence */
|
|
+ for (int i = 0; i < occurrence; i++) {
|
|
+ p = strstr(p + 1, subs);
|
|
+ assert_non_null(p);
|
|
+ }
|
|
+ memmove(p, p + strlen(subs), strlen(p + strlen(subs)) + 1);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '+' feature works
|
|
+ */
|
|
+static void torture_config_plus(void **state,
|
|
+ const char *file, const char *string)
|
|
+{
|
|
+ ssh_session session = *state;
|
|
+ const char *def_hostkeys = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
|
+ const char *fips_hostkeys = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
|
+ const char *def_ciphers = ssh_kex_get_default_methods(SSH_CRYPT_C_S);
|
|
+ const char *fips_ciphers = ssh_kex_get_fips_methods(SSH_CRYPT_C_S);
|
|
+ const char *def_kex = ssh_kex_get_default_methods(SSH_KEX);
|
|
+ const char *fips_kex = ssh_kex_get_fips_methods(SSH_KEX);
|
|
+ const char *def_mac = ssh_kex_get_default_methods(SSH_MAC_C_S);
|
|
+ const char *fips_mac = ssh_kex_get_fips_methods(SSH_MAC_C_S);
|
|
+ const char *hostkeys_added = ",ssh-rsa";
|
|
+ const char *ciphers_added = "aes128-cbc,aes256-cbc";
|
|
+ const char *kex_added = ",diffie-hellman-group14-sha1,diffie-hellman-group1-sha1";
|
|
+ const char *mac_added = ",hmac-sha1,hmac-sha1-etm@openssh.com";
|
|
+ char *awaited = NULL;
|
|
+ int rc;
|
|
+
|
|
+ _parse_config(session, file, string, SSH_OK);
|
|
+
|
|
+ /* check hostkeys */
|
|
+ if (ssh_fips_mode()) {
|
|
+ /* ssh-rsa is disabled in fips */
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], fips_hostkeys);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_hostkeys) + strlen(hostkeys_added) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(def_hostkeys) + strlen(hostkeys_added) + 1,
|
|
+ "%s%s", def_hostkeys, hostkeys_added);
|
|
+ assert_int_equal(rc, strlen(def_hostkeys) + strlen(hostkeys_added));
|
|
+
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], awaited);
|
|
+ free(awaited);
|
|
+ }
|
|
+
|
|
+ /* check ciphers */
|
|
+ if (ssh_fips_mode()) {
|
|
+ /* already all supported is in the list */
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_CRYPT_C_S], fips_ciphers);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_ciphers) + strlen(ciphers_added) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(def_ciphers) + strlen(ciphers_added) + 1,
|
|
+ "%s%s", def_ciphers, ciphers_added);
|
|
+ assert_int_equal(rc, strlen(def_ciphers) + strlen(ciphers_added));
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_CRYPT_C_S], awaited);
|
|
+ free(awaited);
|
|
+ }
|
|
+
|
|
+ /* check kex */
|
|
+ if (ssh_fips_mode()) {
|
|
+ /* sha1 is disabled in fips */
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_KEX], fips_kex);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_kex) + strlen(kex_added) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(def_kex) + strlen(kex_added) + 1,
|
|
+ "%s%s", def_kex, kex_added);
|
|
+ assert_int_equal(rc, strlen(def_kex) + strlen(kex_added));
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_KEX], awaited);
|
|
+ free(awaited);
|
|
+ }
|
|
+
|
|
+ /* check mac */
|
|
+ if (ssh_fips_mode()) {
|
|
+ /* the added algos are already in the fips_methods */
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], fips_mac);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_mac) + strlen(mac_added) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(def_mac) + strlen(mac_added) + 1,
|
|
+ "%s%s", def_mac, mac_added);
|
|
+ assert_int_equal(rc, strlen(def_mac) + strlen(mac_added));
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], awaited);
|
|
+ free(awaited);
|
|
+ }
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '+' feature works from file
|
|
+ */
|
|
+static void torture_config_plus_file(void **state)
|
|
+{
|
|
+ torture_config_plus(state, LIBSSH_TESTCONFIG14, NULL);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '+' feature works from string
|
|
+ */
|
|
+static void torture_config_plus_string(void **state)
|
|
+{
|
|
+ torture_config_plus(state, NULL, LIBSSH_TESTCONFIG_STRING14);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '-' feature works from string
|
|
+ */
|
|
+static void torture_config_minus(void **state,
|
|
+ const char *file, const char *string)
|
|
+{
|
|
+ ssh_session session = *state;
|
|
+ const char *def_hostkeys = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
|
+ const char *fips_hostkeys = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
|
+ const char *def_ciphers = ssh_kex_get_default_methods(SSH_CRYPT_C_S);
|
|
+ const char *fips_ciphers = ssh_kex_get_fips_methods(SSH_CRYPT_C_S);
|
|
+ const char *def_kex = ssh_kex_get_default_methods(SSH_KEX);
|
|
+ const char *fips_kex = ssh_kex_get_fips_methods(SSH_KEX);
|
|
+ const char *def_mac = ssh_kex_get_default_methods(SSH_MAC_C_S);
|
|
+ const char *fips_mac = ssh_kex_get_fips_methods(SSH_MAC_C_S);
|
|
+ const char *hostkeys_removed = ",rsa-sha2-512,rsa-sha2-256";
|
|
+ const char *ciphers_removed = ",aes256-ctr";
|
|
+ const char *kex_removed = ",diffie-hellman-group18-sha512,diffie-hellman-group16-sha512";
|
|
+ const char *fips_kex_removed = ",diffie-hellman-group16-sha512,diffie-hellman-group18-sha512";
|
|
+ const char *mac_removed = "hmac-sha2-256-etm@openssh.com,";
|
|
+ char *awaited = NULL;
|
|
+ int rc;
|
|
+
|
|
+ _parse_config(session, file, string, SSH_OK);
|
|
+
|
|
+ /* check hostkeys */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = calloc(strlen(fips_hostkeys) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(fips_hostkeys) + 1, "%s", fips_hostkeys);
|
|
+ assert_int_equal(rc, strlen(fips_hostkeys));
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_hostkeys) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(def_hostkeys) + 1, "%s", def_hostkeys);
|
|
+ assert_int_equal(rc, strlen(def_hostkeys));
|
|
+ }
|
|
+ /* remove the substring from the defaults */
|
|
+ helper_remove_substring(awaited, hostkeys_removed, 0);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], awaited);
|
|
+ free(awaited);
|
|
+
|
|
+ /* check ciphers */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = calloc(strlen(fips_ciphers) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(fips_ciphers) + 1, "%s", fips_ciphers);
|
|
+ assert_int_equal(rc, strlen(fips_ciphers));
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_ciphers) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(def_ciphers) + 1, "%s", def_ciphers);
|
|
+ assert_int_equal(rc, strlen(def_ciphers));
|
|
+ /* remove the comma at the end of the list */
|
|
+ awaited[strlen(awaited) - 1] = '\0';
|
|
+ }
|
|
+ /* remove the substring from the defaults */
|
|
+ helper_remove_substring(awaited, ciphers_removed, 0);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_CRYPT_C_S], awaited);
|
|
+ free(awaited);
|
|
+
|
|
+ /* check kex */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = calloc(strlen(fips_kex) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(fips_kex) + 1, "%s", fips_kex);
|
|
+ assert_int_equal(rc, strlen(fips_kex));
|
|
+ /* remove the substring from the defaults */
|
|
+ helper_remove_substring(awaited, fips_kex_removed, 0);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_kex) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(def_kex) + 1, "%s", def_kex);
|
|
+ assert_int_equal(rc, strlen(def_kex));
|
|
+ /* remove the substring from the defaults */
|
|
+ helper_remove_substring(awaited, kex_removed, 0);
|
|
+ }
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_KEX], awaited);
|
|
+ free(awaited);
|
|
+
|
|
+ /* check mac */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = calloc(strlen(fips_mac) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(fips_mac) + 1, "%s", fips_mac);
|
|
+ assert_int_equal(rc, strlen(fips_mac));
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_mac) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(def_mac) + 1, "%s", def_mac);
|
|
+ assert_int_equal(rc, strlen(def_mac));
|
|
+ }
|
|
+ /* remove the substring from the defaults */
|
|
+ helper_remove_substring(awaited, mac_removed, 0);
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], awaited);
|
|
+ free(awaited);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '-' feature works from file
|
|
+ */
|
|
+static void torture_config_minus_file(void **state)
|
|
+{
|
|
+ torture_config_minus(state, LIBSSH_TESTCONFIG15, NULL);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '-' feature works from string
|
|
+ */
|
|
+static void torture_config_minus_string(void **state)
|
|
+{
|
|
+ torture_config_minus(state, NULL, LIBSSH_TESTCONFIG_STRING15);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '^' feature works from string
|
|
+ */
|
|
+static void torture_config_caret(void **state,
|
|
+ const char *file, const char *string)
|
|
+{
|
|
+ ssh_session session = *state;
|
|
+ const char *def_hostkeys = ssh_kex_get_default_methods(SSH_HOSTKEYS);
|
|
+ const char *fips_hostkeys = ssh_kex_get_fips_methods(SSH_HOSTKEYS);
|
|
+ const char *def_ciphers = ssh_kex_get_default_methods(SSH_CRYPT_C_S);
|
|
+ const char *fips_ciphers = ssh_kex_get_fips_methods(SSH_CRYPT_C_S);
|
|
+ const char *def_kex = ssh_kex_get_default_methods(SSH_KEX);
|
|
+ const char *fips_kex = ssh_kex_get_fips_methods(SSH_KEX);
|
|
+ const char *def_mac = ssh_kex_get_default_methods(SSH_MAC_C_S);
|
|
+ const char *fips_mac = ssh_kex_get_fips_methods(SSH_MAC_C_S);
|
|
+ const char *hostkeys_prio = "rsa-sha2-512,rsa-sha2-256";
|
|
+ const char *ciphers_prio = "aes256-cbc,";
|
|
+ const char *kex_prio = "diffie-hellman-group18-sha512,diffie-hellman-group16-sha512,";
|
|
+ const char *fips_kex_prio = ",diffie-hellman-group16-sha512,diffie-hellman-group18-sha512";
|
|
+ const char *mac_prio = "hmac-sha1,";
|
|
+ char *awaited = NULL;
|
|
+ int rc;
|
|
+
|
|
+ _parse_config(session, file, string, SSH_OK);
|
|
+
|
|
+ /* check hostkeys */
|
|
+ /* +2 for the added comma and the \0 */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = calloc(strlen(hostkeys_prio) + strlen(fips_hostkeys) + 2, 1);
|
|
+ rc = snprintf(awaited, strlen(hostkeys_prio) + strlen(fips_hostkeys) + 2,
|
|
+ "%s,%s", hostkeys_prio, fips_hostkeys);
|
|
+ assert_int_equal(rc, strlen(hostkeys_prio) + strlen(fips_hostkeys) + 1);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(def_hostkeys) + strlen(hostkeys_prio) + 2, 1);
|
|
+ rc = snprintf(awaited, strlen(hostkeys_prio) + strlen(def_hostkeys) + 2,
|
|
+ "%s,%s", hostkeys_prio, def_hostkeys);
|
|
+ assert_int_equal(rc, strlen(hostkeys_prio) + strlen(def_hostkeys) + 1);
|
|
+ }
|
|
+
|
|
+ /* remove the substring from the defaults */
|
|
+ helper_remove_substring(awaited, hostkeys_prio, 1);
|
|
+ /* remove the comma at the end of the list */
|
|
+ awaited[strlen(awaited) - 1] = '\0';
|
|
+
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_HOSTKEYS], awaited);
|
|
+ free(awaited);
|
|
+
|
|
+ /* check ciphers */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = calloc(strlen(ciphers_prio) + strlen(fips_ciphers) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(ciphers_prio) + strlen(fips_ciphers) + 1,
|
|
+ "%s%s", ciphers_prio, fips_ciphers);
|
|
+ assert_int_equal(rc, strlen(ciphers_prio) + strlen(fips_ciphers));
|
|
+ /* remove the substring from the defaults */
|
|
+ helper_remove_substring(awaited, ciphers_prio, 1);
|
|
+ } else {
|
|
+ /* + 2 because the '\0' and the comma */
|
|
+ awaited = calloc(strlen(ciphers_prio) + strlen(def_ciphers) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(ciphers_prio) + strlen(def_ciphers) + 1,
|
|
+ "%s%s", ciphers_prio, def_ciphers);
|
|
+ assert_int_equal(rc, strlen(ciphers_prio) + strlen(def_ciphers));
|
|
+ /* remove the comma at the end of the list */
|
|
+ awaited[strlen(awaited) - 1] = '\0';
|
|
+ }
|
|
+
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_CRYPT_C_S], awaited);
|
|
+ free(awaited);
|
|
+
|
|
+ /* check kex */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = calloc(strlen(kex_prio) + strlen(fips_kex) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(kex_prio) + strlen(fips_kex) + 1,
|
|
+ "%s%s", kex_prio, fips_kex);
|
|
+ assert_int_equal(rc, strlen(kex_prio) + strlen(fips_kex));
|
|
+ /* remove the substring from the defaults */
|
|
+ /* the default list has different order of these two algos than the fips
|
|
+ * and because here is a braindead string substitution being done,
|
|
+ * change the order and remove the first occurrence of it */
|
|
+ helper_remove_substring(awaited, fips_kex_prio, 0);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(kex_prio) + strlen(def_kex) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(kex_prio) + strlen(def_kex) + 1,
|
|
+ "%s%s", kex_prio, def_kex);
|
|
+ assert_int_equal(rc, strlen(def_kex) + strlen(kex_prio));
|
|
+ /* remove the substring from the defaults */
|
|
+ helper_remove_substring(awaited, kex_prio, 1);
|
|
+ }
|
|
+
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_KEX], awaited);
|
|
+ free(awaited);
|
|
+
|
|
+ /* check mac */
|
|
+ if (ssh_fips_mode()) {
|
|
+ awaited = calloc(strlen(mac_prio) + strlen(fips_mac) + 1, 1);
|
|
+ rc = snprintf(awaited, strlen(mac_prio) + strlen(fips_mac) + 1, "%s%s", mac_prio, fips_mac);
|
|
+ assert_int_equal(rc, strlen(mac_prio) + strlen(fips_mac));
|
|
+ /* the fips list contains hmac-sha1 algo */
|
|
+ helper_remove_substring(awaited, mac_prio, 1);
|
|
+ } else {
|
|
+ awaited = calloc(strlen(mac_prio) + strlen(def_mac) + 1, 1);
|
|
+ /* the mac is not in default; it is added to the list */
|
|
+ rc = snprintf(awaited, strlen(mac_prio) + strlen(def_mac) + 1, "%s%s", mac_prio, def_mac);
|
|
+ assert_int_equal(rc, strlen(mac_prio) + strlen(def_mac));
|
|
+ }
|
|
+ assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], awaited);
|
|
+ free(awaited);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '^' feature works from file
|
|
+ */
|
|
+static void torture_config_caret_file(void **state)
|
|
+{
|
|
+ torture_config_caret(state, LIBSSH_TESTCONFIG16, NULL);
|
|
+}
|
|
+
|
|
+/**
|
|
+ * @brief test that openssh style '^' feature works from string
|
|
+ */
|
|
+static void torture_config_caret_string(void **state)
|
|
+{
|
|
+ torture_config_caret(state, NULL, LIBSSH_TESTCONFIG_STRING16);
|
|
+}
|
|
+
|
|
/**
|
|
* @brief test PubkeyAcceptedKeyTypes helper function
|
|
*/
|
|
@@ -1848,6 +2229,18 @@ int torture_run_tests(void)
|
|
setup, teardown),
|
|
cmocka_unit_test_setup_teardown(torture_config_rekey_string,
|
|
setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_config_plus_file,
|
|
+ setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_config_plus_string,
|
|
+ setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_config_minus_file,
|
|
+ setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_config_minus_string,
|
|
+ setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_config_caret_file,
|
|
+ setup, teardown),
|
|
+ cmocka_unit_test_setup_teardown(torture_config_caret_string,
|
|
+ setup, teardown),
|
|
cmocka_unit_test_setup_teardown(torture_config_pubkeytypes_file,
|
|
setup, teardown),
|
|
cmocka_unit_test_setup_teardown(torture_config_pubkeytypes_string,
|
|
--
|
|
2.38.1
|
|
|