]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: add MACsec*Association.KeyFile= setting
authorYu Watanabe <watanabe.yu+github@gmail.com>
Wed, 10 Apr 2019 09:07:10 +0000 (18:07 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Fri, 12 Apr 2019 01:12:42 +0000 (10:12 +0900)
man/systemd.netdev.xml
src/network/netdev/macsec.c
src/network/netdev/macsec.h
src/network/netdev/netdev-gperf.gperf
test/fuzz/fuzz-netdev-parser/directives.netdev

index 9b131a16b67068564c4e1266a6f37ea6277be5c5..7ab9faac6da653ca14b878e62a648dc96ec90e9f 100644 (file)
           <literal>dffafc8d7b9a43d5b9a3dfbbf6a30c16</literal>.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>KeyFile=</varname></term>
+        <listitem>
+          <para>Takes a absolute path to a file which contains a 128-bit key encoded in a hexadecimal
+          string, which will be used in the transmission channel. When this option is specified,
+          <varname>Key=</varname> is ignored. Note that the file must be readable by the user
+          <literal>systemd-network</literal>, so it should be, e.g., owned by
+          <literal>root:systemd-network</literal> with a <literal>0640</literal> file mode.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
           <para>Accepts the same key in <literal>[MACsecTransmitAssociation]</literal> section.</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>KeyFile=</varname></term>
+        <listitem>
+          <para>Accepts the same key in <literal>[MACsecTransmitAssociation]</literal> section.</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
   <refsect1>
index 01c9beaa07f35db26be6ca2323dfd530c5d1a0ba..977c03eeb1ba0e921e285199524ee4054ad577ad 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/genetlink.h>
 
 #include "conf-parser.h"
+#include "fileio.h"
 #include "hashmap.h"
 #include "hexdecoct.h"
 #include "macsec.h"
@@ -15,6 +16,7 @@
 #include "network-internal.h"
 #include "networkd-address.h"
 #include "networkd-manager.h"
+#include "path-util.h"
 #include "sd-netlink.h"
 #include "socket-util.h"
 #include "string-table.h"
@@ -27,6 +29,7 @@ static void security_association_clear(SecurityAssociation *sa) {
 
         explicit_bzero_safe(sa->key, sa->key_len);
         free(sa->key);
+        free(sa->key_file);
 }
 
 static void macsec_receive_association_free(ReceiveAssociation *c) {
@@ -738,6 +741,59 @@ int config_parse_macsec_key(
         return 0;
 }
 
+int config_parse_macsec_key_file(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
+        _cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
+        _cleanup_free_ char *path = NULL;
+        MACsec *s = userdata;
+        char **dest;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (streq(section, "MACsecTransmitAssociation"))
+                r = macsec_transmit_association_new_static(s, filename, section_line, &a);
+        else
+                r = macsec_receive_association_new_static(s, filename, section_line, &b);
+        if (r < 0)
+                return r;
+
+        dest = a ? &a->sa.key_file : &b->sa.key_file;
+
+        if (isempty(rvalue)) {
+                *dest = mfree(*dest);
+                return 0;
+        }
+
+        path = strdup(rvalue);
+        if (!path)
+                return log_oom();
+
+        if (path_simplify_and_warn(path, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue) < 0)
+                return 0;
+
+        free_and_replace(*dest, path);
+        TAKE_PTR(a);
+        TAKE_PTR(b);
+
+        return 0;
+}
+
 int config_parse_macsec_key_id(
                 const char *unit,
                 const char *filename,
@@ -793,6 +849,36 @@ int config_parse_macsec_key_id(
         return 0;
 }
 
+static int macsec_read_key_file(NetDev *netdev, SecurityAssociation *sa) {
+        _cleanup_free_ uint8_t *key = NULL;
+        size_t key_len;
+        int r;
+
+        assert(netdev);
+        assert(sa);
+
+        if (!sa->key_file)
+                return 0;
+
+        r = read_full_file_full(sa->key_file, READ_FULL_FILE_SECURE | READ_FULL_FILE_UNHEX, (char **) &key, &key_len);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r,
+                                              "Failed to read key from '%s', ignoring: %m",
+                                              sa->key_file);
+        if (key_len != 16) {
+                explicit_bzero_safe(key, key_len);
+                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                              "Invalid key length (%zu bytes), ignoring: %m",
+                                              key_len);
+        }
+
+        explicit_bzero_safe(sa->key, sa->key_len);
+        free_and_replace(sa->key, key);
+        sa->key_len = key_len;
+
+        return 0;
+}
+
 static int macsec_receive_channel_verify(ReceiveChannel *c) {
         NetDev *netdev;
         int r;
@@ -837,6 +923,7 @@ static int macsec_receive_channel_verify(ReceiveChannel *c) {
 
 static int macsec_transmit_association_verify(TransmitAssociation *t) {
         NetDev *netdev;
+        int r;
 
         assert(t);
         assert(t->macsec);
@@ -852,6 +939,10 @@ static int macsec_transmit_association_verify(TransmitAssociation *t) {
                                               "Ignoring [MACsecTransmitAssociation] section from line %u",
                                               t->section->filename, t->section->line);
 
+        r = macsec_read_key_file(netdev, &t->sa);
+        if (r < 0)
+                return r;
+
         if (t->sa.key_len <= 0)
                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
                                               "%s: MACsec transmit secure association without key configured. "
@@ -874,6 +965,10 @@ static int macsec_receive_association_verify(ReceiveAssociation *a) {
         if (section_is_invalid(a->section))
                 return -EINVAL;
 
+        r = macsec_read_key_file(netdev, &a->sa);
+        if (r < 0)
+                return r;
+
         if (a->sa.key_len <= 0)
                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
                                               "%s: MACsec receive secure association without key configured. "
index 55d95b475a2bb83e819a934b9e5d5b697e2aab63..36c90d47ab4502dce31e3bf4dc5b5325f7f35bb0 100644 (file)
@@ -30,6 +30,7 @@ typedef struct SecurityAssociation {
         uint8_t key_id[MACSEC_KEYID_LEN];
         uint8_t *key;
         uint32_t key_len;
+        char *key_file;
 } SecurityAssociation;
 
 typedef struct TransmitAssociation {
@@ -76,3 +77,4 @@ CONFIG_PARSER_PROTOTYPE(config_parse_macsec_hw_address);
 CONFIG_PARSER_PROTOTYPE(config_parse_macsec_packet_number);
 CONFIG_PARSER_PROTOTYPE(config_parse_macsec_key_id);
 CONFIG_PARSER_PROTOTYPE(config_parse_macsec_key);
+CONFIG_PARSER_PROTOTYPE(config_parse_macsec_key_file);
index 6dd8e10d597404a39b2079abab44a69ec62e7d4f..d06ef23a8ba3a27cbfb8ac63de062064ab639dea 100644 (file)
@@ -140,11 +140,13 @@ MACsecReceiveChannel.MACAddress,   config_parse_macsec_hw_address,       0,
 MACsecTransmitAssociation.PacketNumber, config_parse_macsec_packet_number, 0,                           0
 MACsecTransmitAssociation.KeyId,   config_parse_macsec_key_id,           0,                             0
 MACsecTransmitAssociation.Key,     config_parse_macsec_key,              0,                             0
+MACsecTransmitAssociation.KeyFile, config_parse_macsec_key_file,         0,                             0
 MACsecReceiveAssociation.Port,     config_parse_macsec_port,             0,                             0
 MACsecReceiveAssociation.MACAddress, config_parse_macsec_hw_address,     0,                             0
 MACsecReceiveAssociation.PacketNumber, config_parse_macsec_packet_number, 0,                            0
 MACsecReceiveAssociation.KeyId,    config_parse_macsec_key_id,           0,                             0
 MACsecReceiveAssociation.Key,      config_parse_macsec_key,              0,                             0
+MACsecReceiveAssociation.KeyFile,  config_parse_macsec_key_file,         0,                             0
 Tun.OneQueue,                      config_parse_bool,                    0,                             offsetof(TunTap, one_queue)
 Tun.MultiQueue,                    config_parse_bool,                    0,                             offsetof(TunTap, multi_queue)
 Tun.PacketInfo,                    config_parse_bool,                    0,                             offsetof(TunTap, packet_info)
index 9ea34753030e71dcf8e38de160b815e88aab2296..344ffdf9b05624ca65392fe47a9c2c47cc501d90 100644 (file)
@@ -183,6 +183,7 @@ MACAddress=
 PacketNumber=
 KeyId=
 Key=
+KeyFile=
 [MACsecReceiveChannel]
 Port=
 MACAddress=
@@ -190,3 +191,4 @@ MACAddress=
 PacketNumber=
 KeyId=
 Key=
+KeyFile=