]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/plugins/selinux/selinux_listener.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libcharon / plugins / selinux / selinux_listener.c
CommitLineData
b00a4e77 1/*
19ef2aec 2 * Copyright (C) 2022 Tobias Brunner
b00a4e77 3 *
19ef2aec 4 * Copyright (C) secunet Security Networks AG
b00a4e77 5 *
19ef2aec
TB
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
b00a4e77 10 *
19ef2aec
TB
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
b00a4e77
TB
15 */
16
17#include "selinux_listener.h"
18
19#include <daemon.h>
20#include <collections/array.h>
21#include <collections/hashtable.h>
22
23typedef struct private_selinux_listener_t private_selinux_listener_t;
24
25/**
26 * Private data.
27 */
28struct private_selinux_listener_t {
29
30 /**
31 * Public interface.
32 */
33 selinux_listener_t public;
34
35 /**
36 * IKE_SAs with attached trap policies, ike_sa_id_t => entry_t.
37 */
38 hashtable_t *sas;
39};
40
41/**
42 * Entry to keep track of trap policies.
43 */
44typedef struct {
45
46 /**
47 * IKE_SA ID.
48 */
49 ike_sa_id_t *id;
50
51 /**
52 * Installed trap policies.
53 */
54 array_t *traps;
55
56} entry_t;
57
58/**
59 * Destroy the given entry.
60 */
61static void destroy_entry(entry_t *entry)
62{
63 entry->id->destroy(entry->id);
64 array_destroy(entry->traps);
65 free(entry);
66}
67
68/**
69 * Hashtable hash function
70 */
71static u_int hash(const void *key)
72{
73 ike_sa_id_t *id = (ike_sa_id_t*)key;
74 uint64_t spi_i = id->get_initiator_spi(id),
75 spi_r = id->get_responder_spi(id);
76 return chunk_hash_inc(chunk_from_thing(spi_i),
77 chunk_hash(chunk_from_thing(spi_r)));
78}
79
80/**
81 * Hashtable equals function
82 */
83static bool equals(const void *a_pub, const void *b)
84{
85 ike_sa_id_t *a = (ike_sa_id_t*)a_pub;
86 return a->equals(a, (ike_sa_id_t*)b);
87}
88
89/**
90 * Install a trap policy for the generic SELinux label.
91 */
92static bool install_generic_trap(ike_sa_t *ike_sa, child_sa_t *child_sa)
93{
94 linked_list_t *local, *remote;
95 sec_label_t *label;
96 bool success;
97
98 label = child_sa->get_label(child_sa);
99 DBG1(DBG_IKE, "installing trap %s{%d} with generic security label '%s'",
100 child_sa->get_name(child_sa), child_sa->get_unique_id(child_sa),
101 label->get_string(label));
102
103 local = ike_sa_get_dynamic_hosts(ike_sa, TRUE);
104 remote = ike_sa_get_dynamic_hosts(ike_sa, FALSE);
105 success = charon->traps->install_external(charon->traps,
106 ike_sa->get_peer_cfg(ike_sa),
107 child_sa, local, remote);
108 local->destroy(local);
109 remote->destroy(remote);
110 return success;
111}
112
113METHOD(listener_t, ike_updown, bool,
114 private_selinux_listener_t *this, ike_sa_t *ike_sa, bool up)
115{
116 enumerator_t *enumerator;
117 peer_cfg_t *peer_cfg;
118 child_cfg_t *child_cfg;
119 child_sa_t *child_sa;
120 entry_t *entry;
121
122 if (up)
123 {
124 child_sa_create_t child = {
125 .if_id_in_def = ike_sa->get_if_id(ike_sa, TRUE),
126 .if_id_out_def = ike_sa->get_if_id(ike_sa, FALSE),
127 };
128
129 INIT(entry,
130 .id = ike_sa->get_id(ike_sa),
131 );
132 entry->id = entry->id->clone(entry->id);
133
134 peer_cfg = ike_sa->get_peer_cfg(ike_sa);
135 enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
136 while (enumerator->enumerate(enumerator, &child_cfg))
137 {
138 if (child_cfg->get_label(child_cfg) &&
139 child_cfg->get_label_mode(child_cfg) == SEC_LABEL_MODE_SELINUX)
140 {
141 child_sa = child_sa_create(ike_sa->get_my_host(ike_sa),
142 ike_sa->get_other_host(ike_sa),
143 child_cfg, &child);
144 if (install_generic_trap(ike_sa, child_sa))
145 {
146 array_insert_create(&entry->traps, ARRAY_TAIL, child_sa);
147 }
148 else
149 {
150 child_sa->destroy(child_sa);
151 }
152 }
153 }
154 enumerator->destroy(enumerator);
155
156 if (array_count(entry->traps))
157 {
158 this->sas->put(this->sas, entry->id, entry);
159 }
160 else
161 {
162 destroy_entry(entry);
163 }
164 }
165 else
166 {
167 entry = this->sas->remove(this->sas, ike_sa->get_id(ike_sa));
168 if (entry)
169 {
170 while (array_remove(entry->traps, ARRAY_TAIL, &child_sa))
171 {
172 sec_label_t *label = child_sa->get_label(child_sa);
173
174 DBG1(DBG_IKE, "uninstalling trap %s{%d} with generic security "
175 "label '%s'", child_sa->get_name(child_sa),
176 child_sa->get_unique_id(child_sa),
177 label->get_string(label));
178 charon->traps->remove_external(charon->traps, child_sa);
179 child_sa->destroy(child_sa);
180 }
181 destroy_entry(entry);
182 }
183 }
184 return TRUE;
185}
186
187METHOD(listener_t, ike_rekey, bool,
188 private_selinux_listener_t *this, ike_sa_t *old, ike_sa_t *new)
189{
190 entry_t *entry;
191
192 entry = this->sas->remove(this->sas, old->get_id(old));
193 if (entry)
194 {
195 entry->id->destroy(entry->id);
196 entry->id = new->get_id(new);
197 entry->id = entry->id->clone(entry->id);
198 this->sas->put(this->sas, entry->id, entry);
199 }
200 return TRUE;
201}
202
203METHOD(listener_t, ike_update, bool,
204 private_selinux_listener_t *this, ike_sa_t *ike_sa,
205 host_t *local, host_t *remote)
206{
207 entry_t *entry;
208 child_sa_t *child_sa;
209 linked_list_t *vips;
210 int i;
211
212 entry = this->sas->get(this->sas, ike_sa->get_id(ike_sa));
213 if (entry)
214 {
215 vips = linked_list_create_from_enumerator(
216 ike_sa->create_virtual_ip_enumerator(ike_sa, local));
217 for (i = 0; i < array_count(entry->traps); i++)
218 {
219 array_get(entry->traps, i, &child_sa);
220 child_sa->update(child_sa, local, remote, vips,
221 ike_sa->has_condition(ike_sa, COND_NAT_ANY));
222 }
223 vips->destroy(vips);
224 }
225 return TRUE;
226}
227
228METHOD(selinux_listener_t, destroy, void,
229 private_selinux_listener_t *this)
230{
231 this->sas->destroy(this->sas);
232 free(this);
233}
234
235/*
236 * Described in header
237 */
238selinux_listener_t *selinux_listener_create()
239{
240 private_selinux_listener_t *this;
241
242 INIT(this,
243 .public = {
244 .listener = {
245 .ike_updown = _ike_updown,
246 .ike_rekey = _ike_rekey,
247 .ike_update = _ike_update,
248 },
249 .destroy = _destroy,
250 },
251 .sas = hashtable_create(hash, equals, 32),
252 );
253
254 return &this->public;
255}