]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
kernel-interface: Optionally consider security label when allocating reqids
authorTobias Brunner <tobias@strongswan.org>
Mon, 20 Dec 2021 14:11:37 +0000 (15:11 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 14 Apr 2022 16:42:01 +0000 (18:42 +0200)
src/libcharon/kernel/kernel_interface.c
src/libcharon/kernel/kernel_interface.h
src/libcharon/sa/child_sa.c

index 8f6c21b6152752fd982e8cf0103486edf65723cb..01c814ab5c2d04496eb6fb2e33088abd4dc834b1 100644 (file)
@@ -208,6 +208,8 @@ typedef struct {
        uint32_t if_id_in;
        /** outbound interface ID used for SA */
        uint32_t if_id_out;
+       /** security label */
+       sec_label_t *label;
        /** local traffic selectors */
        array_t *local;
        /** remote traffic selectors */
@@ -221,19 +223,49 @@ static void reqid_entry_destroy(reqid_entry_t *entry)
 {
        array_destroy_offset(entry->local, offsetof(traffic_selector_t, destroy));
        array_destroy_offset(entry->remote, offsetof(traffic_selector_t, destroy));
+       DESTROY_IF(entry->label);
        free(entry);
 }
 
+/**
+ * Hash the shared data of reqid entries
+ */
+static u_int entry_hash_shared(reqid_entry_t *entry)
+{
+       u_int hash;
+
+       hash = chunk_hash_inc(chunk_from_thing(entry->mark_in),
+                               chunk_hash_inc(chunk_from_thing(entry->mark_out),
+                                       chunk_hash_inc(chunk_from_thing(entry->if_id_in),
+                                               chunk_hash(chunk_from_thing(entry->if_id_out)))));
+       if (entry->label)
+       {
+               hash = entry->label->hash(entry->label, hash);
+       }
+       return hash;
+}
+
+/**
+ * Compare the shared properties of reqid entries
+ */
+static bool entry_equals_shared(reqid_entry_t *a, reqid_entry_t *b)
+{
+       return a->mark_in.value == b->mark_in.value &&
+                  a->mark_in.mask == b->mark_in.mask &&
+                  a->mark_out.value == b->mark_out.value &&
+                  a->mark_out.mask == b->mark_out.mask &&
+                  a->if_id_in == b->if_id_in &&
+                  a->if_id_out == b->if_id_out &&
+                  sec_labels_equal(a->label, b->label);
+}
+
 /**
  * Hashtable hash function for reqid entries using reqid as key
  */
 static u_int hash_reqid(reqid_entry_t *entry)
 {
        return chunk_hash_inc(chunk_from_thing(entry->reqid),
-                               chunk_hash_inc(chunk_from_thing(entry->mark_in),
-                                       chunk_hash_inc(chunk_from_thing(entry->mark_out),
-                                               chunk_hash_inc(chunk_from_thing(entry->if_id_in),
-                                                       chunk_hash(chunk_from_thing(entry->if_id_out))))));
+                               entry_hash_shared(entry));
 }
 
 /**
@@ -241,13 +273,11 @@ static u_int hash_reqid(reqid_entry_t *entry)
  */
 static bool equals_reqid(reqid_entry_t *a, reqid_entry_t *b)
 {
-       return a->reqid == b->reqid &&
-                  a->mark_in.value == b->mark_in.value &&
-                  a->mark_in.mask == b->mark_in.mask &&
-                  a->mark_out.value == b->mark_out.value &&
-                  a->mark_out.mask == b->mark_out.mask &&
-                  a->if_id_in == b->if_id_in &&
-                  a->if_id_out == b->if_id_out;
+       if (a->reqid == b->reqid)
+       {
+               return entry_equals_shared(a, b);
+       }
+       return FALSE;
 }
 
 /**
@@ -273,11 +303,9 @@ static u_int hash_ts_array(array_t *array, u_int hash)
  */
 static u_int hash_reqid_by_ts(reqid_entry_t *entry)
 {
-       return hash_ts_array(entry->local, hash_ts_array(entry->remote,
-                       chunk_hash_inc(chunk_from_thing(entry->mark_in),
-                               chunk_hash_inc(chunk_from_thing(entry->mark_out),
-                                       chunk_hash_inc(chunk_from_thing(entry->if_id_in),
-                                               chunk_hash(chunk_from_thing(entry->if_id_out)))))));
+       return hash_ts_array(entry->local,
+                               hash_ts_array(entry->remote,
+                                                entry_hash_shared(entry)));
 }
 
 /**
@@ -311,14 +339,12 @@ static bool ts_array_equals(array_t *a, array_t *b)
  */
 static bool equals_reqid_by_ts(reqid_entry_t *a, reqid_entry_t *b)
 {
-       return ts_array_equals(a->local, b->local) &&
-                  ts_array_equals(a->remote, b->remote) &&
-                  a->mark_in.value == b->mark_in.value &&
-                  a->mark_in.mask == b->mark_in.mask &&
-                  a->mark_out.value == b->mark_out.value &&
-                  a->mark_out.mask == b->mark_out.mask &&
-                  a->if_id_in == b->if_id_in &&
-                  a->if_id_out == b->if_id_out;
+       if (ts_array_equals(a->local, b->local) &&
+               ts_array_equals(a->remote, b->remote))
+       {
+               return entry_equals_shared(a, b);
+       }
+       return FALSE;
 }
 
 /**
@@ -346,7 +372,7 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
        private_kernel_interface_t *this,
        linked_list_t *local_ts, linked_list_t *remote_ts,
        mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out,
-       uint32_t *reqid)
+       sec_label_t *label, uint32_t *reqid)
 {
        static uint32_t counter = 0;
        reqid_entry_t *entry = NULL, *tmpl;
@@ -359,6 +385,7 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
                .mark_out = mark_out,
                .if_id_in = if_id_in,
                .if_id_out = if_id_out,
+               .label = label ? label->clone(label) : NULL,
                .reqid = *reqid,
        );
 
@@ -404,7 +431,8 @@ METHOD(kernel_interface_t, alloc_reqid, status_t,
 
 METHOD(kernel_interface_t, release_reqid, status_t,
        private_kernel_interface_t *this, uint32_t reqid,
-       mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out)
+       mark_t mark_in, mark_t mark_out, uint32_t if_id_in, uint32_t if_id_out,
+       sec_label_t *label)
 {
        reqid_entry_t *entry, tmpl = {
                .reqid = reqid,
@@ -412,6 +440,7 @@ METHOD(kernel_interface_t, release_reqid, status_t,
                .mark_out = mark_out,
                .if_id_in = if_id_in,
                .if_id_out = if_id_out,
+               .label = label,
        };
 
        this->mutex->lock(this->mutex);
index dbc863736b3d2cb45539cf40cb6125b61626885d..fd5685347309508a0d6c3724cb858b83617d1f21 100644 (file)
@@ -145,13 +145,15 @@ struct kernel_interface_t {
         * @param mark_out      outbound mark on SA
         * @param if_id_in      inbound interface ID on SA
         * @param if_id_out     outbound interface ID on SA
+        * @param label         security label (usually the one on the policy, not SA)
         * @param reqid         allocated reqid
         * @return                      SUCCESS if reqid allocated
         */
        status_t (*alloc_reqid)(kernel_interface_t *this,
                                                        linked_list_t *local_ts, linked_list_t *remote_ts,
                                                        mark_t mark_in, mark_t mark_out, uint32_t if_id_in,
-                                                       uint32_t if_id_out, uint32_t *reqid);
+                                                       uint32_t if_id_out, sec_label_t *label,
+                                                       uint32_t *reqid);
 
        /**
         * Release a previously allocated reqid.
@@ -161,11 +163,13 @@ struct kernel_interface_t {
         * @param mark_out      outbound mark on SA
         * @param if_id_in      inbound interface ID on SA
         * @param if_id_out     outbound interface ID on SA
+        * @param label         security label (usually the one on the policy, not SA)
         * @return                      SUCCESS if reqid released
         */
        status_t (*release_reqid)(kernel_interface_t *this, uint32_t reqid,
                                                          mark_t mark_in, mark_t mark_out,
-                                                         uint32_t if_id_in, uint32_t if_id_out);
+                                                         uint32_t if_id_in, uint32_t if_id_out,
+                                                         sec_label_t *label);
 
        /**
         * Add an SA to the SAD.
index f876831382b363e4cfa693b7db969ea245b06068..3c4c1d4393e3ff2afd052027acd5f3279b5aeb9f 100644 (file)
@@ -856,7 +856,7 @@ static status_t install_internal(private_child_sa_t *this, chunk_t encr,
        {
                status = charon->kernel->alloc_reqid(charon->kernel, my_ts, other_ts,
                                                                this->mark_in, this->mark_out, this->if_id_in,
-                                                               this->if_id_out, &this->reqid);
+                                                               this->if_id_out, NULL, &this->reqid);
                if (status != SUCCESS)
                {
                        my_ts->destroy(my_ts);
@@ -1258,7 +1258,7 @@ METHOD(child_sa_t, install_policies, status_t,
                status = charon->kernel->alloc_reqid(
                                                        charon->kernel, my_ts_list, other_ts_list,
                                                        this->mark_in, this->mark_out, this->if_id_in,
-                                                       this->if_id_out, &this->reqid);
+                                                       this->if_id_out, NULL, &this->reqid);
                my_ts_list->destroy(my_ts_list);
                other_ts_list->destroy(other_ts_list);
                if (status != SUCCESS)
@@ -1744,7 +1744,7 @@ METHOD(child_sa_t, destroy, void,
        {
                if (charon->kernel->release_reqid(charon->kernel,
                                                this->reqid, this->mark_in, this->mark_out,
-                                               this->if_id_in, this->if_id_out) != SUCCESS)
+                                               this->if_id_in, this->if_id_out, NULL) != SUCCESS)
                {
                        DBG1(DBG_CHD, "releasing reqid %u failed", this->reqid);
                }