[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] config: Parse KexAlgorithms, MACs, improve Include


Hello,
the attached patch contains a series of patches improving a support for
ssh_config parsing by adding a support for KexAlgorithms and MACs
options.
It is also enhancing Include directive parsing to support glob as it is
currently supported in OpenSSH.

Regards,
-- 
Jakub Jelen
Software Engineer
Security Technologies
Red Hat, Inc.
From 3ecf156ecf7afe0cd623063defd2f075b8dfb426 Mon Sep 17 00:00:00 2001
From: Stefan Dordevic <sdordevi@xxxxxxxxxx>
Date: Mon, 23 Oct 2017 14:32:41 +0200
Subject: [PATCH 1/5] config: Parse KexAlgorithms option

Signed-off-by: Jakub Jelen <jjelen@xxxxxxxxxx>
---
 src/config.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/config.c b/src/config.c
index 25d64998..1429f751 100644
--- a/src/config.c
+++ b/src/config.c
@@ -43,6 +43,7 @@ enum ssh_config_opcode_e {
   SOC_USERNAME,
   SOC_IDENTITY,
   SOC_CIPHERS,
+  SOC_KEXALGORITHMS,
   SOC_COMPRESSION,
   SOC_TIMEOUT,
   SOC_PROTOCOL,
@@ -69,6 +70,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
   { "user", SOC_USERNAME },
   { "identityfile", SOC_IDENTITY },
   { "ciphers", SOC_CIPHERS },
+  { "kexalgorithms", SOC_KEXALGORITHMS },
   { "compression", SOC_COMPRESSION },
   { "connecttimeout", SOC_TIMEOUT },
   { "protocol", SOC_PROTOCOL },
@@ -325,6 +327,12 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
         ssh_options_set(session, SSH_OPTIONS_CIPHERS_S_C, p);
       }
       break;
+    case SOC_KEXALGORITHMS:
+      p = ssh_config_get_str_tok(&s, NULL);
+      if (p && *parsing) {
+        ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, p);
+      }
+      break;
     case SOC_COMPRESSION:
       i = ssh_config_get_yesno(&s, -1);
       if (i >= 0 && *parsing) {
-- 
2.13.6


From c19e78d0e0c7008c2c35a55ff1e2c187b8ac1840 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@xxxxxxxxxx>
Date: Mon, 23 Oct 2017 14:53:55 +0200
Subject: [PATCH 2/5] torture_options: Verify Key exchange algorithms are set
 properly

Signed-off-by: Jakub Jelen <jjelen@xxxxxxxxxx>
---
 tests/unittests/torture_options.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/tests/unittests/torture_options.c b/tests/unittests/torture_options.c
index f3197b8f..79b58a3a 100644
--- a/tests/unittests/torture_options.c
+++ b/tests/unittests/torture_options.c
@@ -59,6 +59,25 @@ static void torture_options_set_ciphers(void **state) {
     assert_false(rc == 0);
 }
 
+static void torture_options_set_key_exchange(void **state) {
+    ssh_session session = *state;
+    int rc;
+
+    /* Test known kexes */
+    rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "curve25519-sha256@xxxxxxxxxx,ecdh-sha2-nistp256,diffie-hellman-group14-sha1");
+    assert_true(rc == 0);
+    assert_string_equal(session->opts.wanted_methods[SSH_KEX], "curve25519-sha256@xxxxxxxxxx,ecdh-sha2-nistp256,diffie-hellman-group14-sha1");
+
+    /* Test one unknown kex */
+    rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "curve25519-sha256@xxxxxxxxxx,unknown-crap@xxxxxxxxxxx,diffie-hellman-group14-sha1");
+    assert_true(rc == 0);
+    assert_string_equal(session->opts.wanted_methods[SSH_KEX], "curve25519-sha256@xxxxxxxxxx,diffie-hellman-group14-sha1");
+
+    /* Test all unknown kexes */
+    rc = ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, "unknown-crap@xxxxxxxxxxx,more-crap@xxxxxxxxxxx");
+    assert_false(rc == 0);
+}
+
 static void torture_options_set_macs(void **state) {
     ssh_session session = *state;
     int rc;
@@ -303,6 +322,7 @@ int torture_run_tests(void) {
         cmocka_unit_test_setup_teardown(torture_options_get_identity, setup, teardown),
         cmocka_unit_test_setup_teardown(torture_options_proxycommand, setup, teardown),
         cmocka_unit_test_setup_teardown(torture_options_set_ciphers, setup, teardown),
+        cmocka_unit_test_setup_teardown(torture_options_set_key_exchange, setup, teardown),
         cmocka_unit_test_setup_teardown(torture_options_set_macs, setup, teardown),
     };
 
-- 
2.13.6


From 721c2101641607fa6ba0a727a23832e26ed93fba Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@xxxxxxxxxx>
Date: Mon, 23 Oct 2017 15:06:12 +0200
Subject: [PATCH 3/5] torture_config: KexAlgorithms parsing in ssh_config

Signed-off-by: Jakub Jelen <jjelen@xxxxxxxxxx>
---
 tests/unittests/torture_config.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/tests/unittests/torture_config.c b/tests/unittests/torture_config.c
index 0b17a7ab..ec0dde53 100644
--- a/tests/unittests/torture_config.c
+++ b/tests/unittests/torture_config.c
@@ -4,6 +4,7 @@
 
 #include "torture.h"
 #include "libssh/options.h"
+#include "libssh/session.h"
 
 #define LIBSSH_TESTCONFIG1 "libssh_testconfig1.tmp"
 #define LIBSSH_TESTCONFIG2 "libssh_testconfig2.tmp"
@@ -13,6 +14,7 @@
 #define USERNAME "testuser"
 #define PROXYCMD "ssh -q -W %h:%p gateway.example.com"
 #define ID_FILE "/etc/xxx"
+#define KEXALGORITHMS "ecdh-sha2-nistp521,diffie-hellman-group14-sha1"
 
 static int setup_config_files(void **state)
 {
@@ -29,7 +31,8 @@ static int setup_config_files(void **state)
                        "Include "LIBSSH_TESTCONFIG3"\n"
                        "ProxyCommand "PROXYCMD"\n\n");
     torture_write_file(LIBSSH_TESTCONFIG3,
-                       "\n\nIdentityFile "ID_FILE"\n");
+                       "\n\nIdentityFile "ID_FILE"\n"
+                       "\n\nKexAlgorithms "KEXALGORITHMS"\n");
 
     /* Multiple Port settings -> parsing returns early. */
     torture_write_file(LIBSSH_TESTCONFIG4,
@@ -85,6 +88,7 @@ static void torture_config_from_file(void **state) {
     assert_string_equal(v, USERNAME);
     ssh_string_free_char(v);
 
+    assert_string_equal(session->opts.wanted_methods[SSH_KEX], KEXALGORITHMS);
 }
 
 /**
-- 
2.13.6


From c9fce1bf48e1c9c89dab1ac31f0be9bf0da41015 Mon Sep 17 00:00:00 2001
From: Jakub Jelen <jjelen@xxxxxxxxxx>
Date: Mon, 23 Oct 2017 16:33:28 +0200
Subject: [PATCH 4/5] config: support for MACs

Signed-off-by: Jakub Jelen <jjelen@xxxxxxxxxx>
---
 src/config.c                      | 9 +++++++++
 tests/unittests/torture_config.c  | 7 ++++++-
 tests/unittests/torture_options.c | 5 +++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/src/config.c b/src/config.c
index 1429f751..553d21bd 100644
--- a/src/config.c
+++ b/src/config.c
@@ -44,6 +44,7 @@ enum ssh_config_opcode_e {
   SOC_IDENTITY,
   SOC_CIPHERS,
   SOC_KEXALGORITHMS,
+  SOC_MACS,
   SOC_COMPRESSION,
   SOC_TIMEOUT,
   SOC_PROTOCOL,
@@ -71,6 +72,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = {
   { "identityfile", SOC_IDENTITY },
   { "ciphers", SOC_CIPHERS },
   { "kexalgorithms", SOC_KEXALGORITHMS },
+  { "macs", SOC_MACS },
   { "compression", SOC_COMPRESSION },
   { "connecttimeout", SOC_TIMEOUT },
   { "protocol", SOC_PROTOCOL },
@@ -333,6 +335,13 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
         ssh_options_set(session, SSH_OPTIONS_KEY_EXCHANGE, p);
       }
       break;
+    case SOC_MACS:
+      p = ssh_config_get_str_tok(&s, NULL);
+      if (p && *parsing) {
+        ssh_options_set(session, SSH_OPTIONS_HMAC_C_S, p);
+        ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, p);
+      }
+      break;
     case SOC_COMPRESSION:
       i = ssh_config_get_yesno(&s, -1);
       if (i >= 0 && *parsing) {
diff --git a/tests/unittests/torture_config.c b/tests/unittests/torture_config.c
index ec0dde53..a0b40239 100644
--- a/tests/unittests/torture_config.c
+++ b/tests/unittests/torture_config.c
@@ -15,6 +15,7 @@
 #define PROXYCMD "ssh -q -W %h:%p gateway.example.com"
 #define ID_FILE "/etc/xxx"
 #define KEXALGORITHMS "ecdh-sha2-nistp521,diffie-hellman-group14-sha1"
+#define MACS "hmac-sha1,hmac-sha2-256"
 
 static int setup_config_files(void **state)
 {
@@ -32,7 +33,8 @@ static int setup_config_files(void **state)
                        "ProxyCommand "PROXYCMD"\n\n");
     torture_write_file(LIBSSH_TESTCONFIG3,
                        "\n\nIdentityFile "ID_FILE"\n"
-                       "\n\nKexAlgorithms "KEXALGORITHMS"\n");
+                       "\n\nKexAlgorithms "KEXALGORITHMS"\n"
+                       "\n\nMACs "MACS"\n");
 
     /* Multiple Port settings -> parsing returns early. */
     torture_write_file(LIBSSH_TESTCONFIG4,
@@ -89,6 +91,9 @@ static void torture_config_from_file(void **state) {
     ssh_string_free_char(v);
 
     assert_string_equal(session->opts.wanted_methods[SSH_KEX], KEXALGORITHMS);
+
+    assert_string_equal(session->opts.wanted_methods[SSH_MAC_C_S], MACS);
+    assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], MACS);
 }
 
 /**
diff --git a/tests/unittests/torture_options.c b/tests/unittests/torture_options.c
index 79b58a3a..3c1121bb 100644
--- a/tests/unittests/torture_options.c
+++ b/tests/unittests/torture_options.c
@@ -87,6 +87,11 @@ static void torture_options_set_macs(void **state) {
     assert_true(rc == 0);
     assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], "hmac-sha1");
 
+    /* Test multiple known MACs */
+    rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "hmac-sha1,hmac-sha2-256");
+    assert_true(rc == 0);
+    assert_string_equal(session->opts.wanted_methods[SSH_MAC_S_C], "hmac-sha1,hmac-sha2-256");
+
     /* Test unknown MACs */
     rc = ssh_options_set(session, SSH_OPTIONS_HMAC_S_C, "unknown-crap@xxxxxxxxxxx,hmac-sha1,unknown@xxxxxxxxxxx");
     assert_true(rc == 0);
-- 
2.13.6


From 8cced50a32dc7579100e2d024c184115205403ff Mon Sep 17 00:00:00 2001
From: NoName115 <robert.kolcun@xxxxxxxxx>
Date: Wed, 25 Oct 2017 14:20:52 +0200
Subject: [PATCH 5/5] config: glob support for include with test

Signed-off-by: Jakub Jelen <jjelen@xxxxxxxxxx>
---
 src/config.c                     | 28 +++++++++++++++++++++++++++-
 tests/unittests/torture_config.c | 40 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/src/config.c b/src/config.c
index 553d21bd..ff646c3d 100644
--- a/src/config.c
+++ b/src/config.c
@@ -27,6 +27,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include <glob.h>
 
 #include "libssh/priv.h"
 #include "libssh/session.h"
@@ -221,6 +222,31 @@ static void local_parse_file(ssh_session session, const char *filename, int *par
   return;
 }
 
+static void local_parse_glob(ssh_session session, const char *fileglob, int *parsing, int seen[]) {
+  glob_t globbuf;
+  int rt;
+  u_int i;
+
+  memset(&globbuf, 0, sizeof(globbuf));
+  rt = glob(fileglob, GLOB_TILDE, NULL, &globbuf);
+  if (rt == GLOB_NOMATCH) {
+    globfree(&globbuf);
+    return;
+  }
+  else if (rt != 0) {
+    SSH_LOG(SSH_LOG_RARE, "Glob error: %s",
+          fileglob);
+    globfree(&globbuf);
+    return;
+  }
+
+  for (i = 0; i < globbuf.gl_pathc; i++) {
+    local_parse_file(session, globbuf.gl_pathv[i], parsing, seen);
+  }
+
+  globfree(&globbuf);
+}
+
 static int ssh_config_parse_line(ssh_session session, const char *line,
     unsigned int count, int *parsing, int seen[]) {
   enum ssh_config_opcode_e opcode;
@@ -266,7 +292,7 @@ static int ssh_config_parse_line(ssh_session session, const char *line,
 
       p = ssh_config_get_str_tok(&s, NULL);
       if (p && *parsing) {
-        local_parse_file(session, p, parsing, seen);
+        local_parse_glob(session, p, parsing, seen);
       }
       break;
     case SOC_HOST: {
diff --git a/tests/unittests/torture_config.c b/tests/unittests/torture_config.c
index a0b40239..8ca097c7 100644
--- a/tests/unittests/torture_config.c
+++ b/tests/unittests/torture_config.c
@@ -10,6 +10,9 @@
 #define LIBSSH_TESTCONFIG2 "libssh_testconfig2.tmp"
 #define LIBSSH_TESTCONFIG3 "libssh_testconfig3.tmp"
 #define LIBSSH_TESTCONFIG4 "libssh_testconfig4.tmp"
+#define LIBSSH_TESTCONFIG5 "libssh_testconfig5.tmp"
+#define LIBSSH_TESTCONFIG6 "libssh_testconfig6.tmp"
+#define LIBSSH_TESTCONFIGGLOB "libssh_testc*[36].tmp"
 
 #define USERNAME "testuser"
 #define PROXYCMD "ssh -q -W %h:%p gateway.example.com"
@@ -25,6 +28,8 @@ static int setup_config_files(void **state)
     unlink(LIBSSH_TESTCONFIG2);
     unlink(LIBSSH_TESTCONFIG3);
     unlink(LIBSSH_TESTCONFIG4);
+    unlink(LIBSSH_TESTCONFIG5);
+    unlink(LIBSSH_TESTCONFIG6);
 
     torture_write_file(LIBSSH_TESTCONFIG1,
                        "User "USERNAME"\nInclude "LIBSSH_TESTCONFIG2"\n\n");
@@ -40,6 +45,13 @@ static int setup_config_files(void **state)
     torture_write_file(LIBSSH_TESTCONFIG4,
                        "Port 123\nPort 456\n");
 
+    /* Testing glob include */
+    torture_write_file(LIBSSH_TESTCONFIG5,
+                        "User "USERNAME"\nInclude "LIBSSH_TESTCONFIGGLOB"\n\n");
+
+    torture_write_file(LIBSSH_TESTCONFIG6,
+                        "ProxyCommand "PROXYCMD"\n\n");
+
     session = ssh_new();
     *state = session;
 
@@ -52,6 +64,8 @@ static int teardown(void **state)
     unlink(LIBSSH_TESTCONFIG2);
     unlink(LIBSSH_TESTCONFIG3);
     unlink(LIBSSH_TESTCONFIG4);
+    unlink(LIBSSH_TESTCONFIG5);
+    unlink(LIBSSH_TESTCONFIG6);
 
     ssh_free(*state);
 
@@ -105,6 +119,29 @@ static void torture_config_double_ports(void **state) {
     assert_true(ret == 0);
 }
 
+static void torture_config_glob(void **state) {
+    ssh_session session = *state;
+    int ret;
+    char *v;
+
+    ret = ssh_config_parse_file(session, LIBSSH_TESTCONFIG5);
+    assert_true(ret == 0);
+
+    /* Test the variable presence */
+
+    ret = ssh_options_get(session, SSH_OPTIONS_PROXYCOMMAND, &v);
+    assert_true(ret == 0);
+
+    assert_string_equal(v, PROXYCMD);
+    ssh_string_free_char(v);
+
+    ret = ssh_options_get(session, SSH_OPTIONS_IDENTITY, &v);
+    assert_true(ret == 0);
+
+    assert_string_equal(v, ID_FILE);
+    ssh_string_free_char(v);
+}
+
 int torture_run_tests(void) {
     int rc;
     struct CMUnitTest tests[] = {
@@ -114,6 +151,9 @@ int torture_run_tests(void) {
         cmocka_unit_test_setup_teardown(torture_config_double_ports,
                                         setup_config_files,
                                         teardown),
+        cmocka_unit_test_setup_teardown(torture_config_glob,
+                                        setup_config_files,
+                                        teardown),
     };
 
 
-- 
2.13.6


Follow-Ups:
Re: [PATCH] config: Parse KexAlgorithms, MACs, improve IncludeJakub Jelen <jjelen@xxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org