Browse code

Trigger a USR1 if dco_update_keys fails

When dco_update_keys fails, we are in some weird state that we are
unlikely to recover since what userspace and kernel space think of
the keys is very likely to not in sync anymore. So abandon the
connection if this happens.

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Antonio Quartulli <antonio@openvpn.net>
Message-Id: <20221213225430.1892940-2-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg25679.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
(cherry picked from commit 419051c96e9fb1f3202fd67733aa3b6a4bbc3181)

Arne Schwabe authored on 2022/12/14 07:54:29
Showing 3 changed files
... ...
@@ -130,7 +130,7 @@ dco_get_secondary_key(struct tls_multi *multi, const struct key_state *primary)
130 130
     return NULL;
131 131
 }
132 132
 
133
-void
133
+bool
134 134
 dco_update_keys(dco_context_t *dco, struct tls_multi *multi)
135 135
 {
136 136
     msg(D_DCO_DEBUG, "%s: peer_id=%d", __func__, multi->dco_peer_id);
... ...
@@ -140,7 +140,7 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi)
140 140
      */
141 141
     if (multi->dco_keys_installed == 0)
142 142
     {
143
-        return;
143
+        return true;
144 144
     }
145 145
 
146 146
     struct key_state *primary = tls_select_encryption_key(multi);
... ...
@@ -155,18 +155,18 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi)
155 155
         if (ret < 0)
156 156
         {
157 157
             msg(D_DCO, "Cannot delete primary key during wipe: %s (%d)", strerror(-ret), ret);
158
-            return;
158
+            return false;
159 159
         }
160 160
 
161 161
         ret = dco_del_key(dco, multi->dco_peer_id, OVPN_KEY_SLOT_SECONDARY);
162 162
         if (ret < 0)
163 163
         {
164 164
             msg(D_DCO, "Cannot delete secondary key during wipe: %s (%d)", strerror(-ret), ret);
165
-            return;
165
+            return false;
166 166
         }
167 167
 
168 168
         multi->dco_keys_installed = 0;
169
-        return;
169
+        return true;
170 170
     }
171 171
 
172 172
     /* if we have a primary key, it must have been installed already (keys
... ...
@@ -198,7 +198,7 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi)
198 198
         if (ret < 0)
199 199
         {
200 200
             msg(D_DCO, "Cannot swap keys: %s (%d)", strerror(-ret), ret);
201
-            return;
201
+            return false;
202 202
         }
203 203
 
204 204
         primary->dco_status = DCO_INSTALLED_PRIMARY;
... ...
@@ -216,7 +216,7 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi)
216 216
         if (ret < 0)
217 217
         {
218 218
             msg(D_DCO, "Cannot delete secondary key: %s (%d)", strerror(-ret), ret);
219
-            return;
219
+            return false;
220 220
         }
221 221
         multi->dco_keys_installed = 1;
222 222
     }
... ...
@@ -230,6 +230,7 @@ dco_update_keys(dco_context_t *dco, struct tls_multi *multi)
230 230
             ks->dco_status = DCO_NOT_INSTALLED;
231 231
         }
232 232
     }
233
+    return true;
233 234
 }
234 235
 
235 236
 static bool
... ...
@@ -164,9 +164,11 @@ int init_key_dco_bi(struct tls_multi *multi, struct key_state *ks,
164 164
  *
165 165
  * @param dco           DCO device context
166 166
  * @param multi         TLS multi instance
167
+ *
168
+ * @return              returns false if an error occurred that is not
169
+ *                      recoverable and should reset the connection
167 170
  */
168
-void dco_update_keys(dco_context_t *dco, struct tls_multi *multi);
169
-
171
+bool dco_update_keys(dco_context_t *dco, struct tls_multi *multi);
170 172
 /**
171 173
  * Install a new peer in DCO - to be called by a CLIENT (or P2P) instance
172 174
  *
... ...
@@ -312,10 +314,11 @@ init_key_dco_bi(struct tls_multi *multi, struct key_state *ks,
312 312
     return 0;
313 313
 }
314 314
 
315
-static inline void
315
+static inline bool
316 316
 dco_update_keys(dco_context_t *dco, struct tls_multi *multi)
317 317
 {
318 318
     ASSERT(false);
319
+    return false;
319 320
 }
320 321
 
321 322
 static inline int
... ...
@@ -151,7 +151,12 @@ check_dco_key_status(struct context *c)
151 151
         return;
152 152
     }
153 153
 
154
-    dco_update_keys(&c->c1.tuntap->dco, c->c2.tls_multi);
154
+    if (!dco_update_keys(&c->c1.tuntap->dco, c->c2.tls_multi))
155
+    {
156
+        /* Something bad happened. Kill the connection to
157
+         * be able to recover. */
158
+        register_signal(c, SIGUSR1, "dco update keys error");
159
+    }
155 160
 }
156 161
 
157 162
 /*