Browse code

stirshaken: Properly handle intermediary/chain certificates when caching certificates - save all certificates provided by signor to the disk cache - properly load all certificates when loading from cache - requires patch to libstirshaken (PR 123); this patch causes no harm (but no benefit) without it - resolve unrelated compiler warnings on 32bit systems

https://github.com/signalwire/libstirshaken/pull/123

Trevor Peirce authored on 02/07/2022 23:46:20
Showing 1 changed files
... ...
@@ -65,7 +65,6 @@ static int w_stirshaken_check_identity_with_key(sip_msg_t *msg, char *pkey_path,
65 65
 static int w_stirshaken_add_identity(sip_msg_t *msg, str *px5u, str *pattest, str *porigtn_val, str *pdesttn_val, str *porigid);
66 66
 static int w_stirshaken_add_identity_with_key(sip_msg_t *msg, str *px5u, str *pattest, str *porigtn_val, str *pdesttn_val, str *porigid, str *pkeypath);
67 67
 
68
-
69 68
 /* clang-format off */
70 69
 static cmd_export_t cmds[]={
71 70
 	{"stirshaken_check_identity", (cmd_function)w_stirshaken_check_identity, 0,
... ...
@@ -158,6 +157,92 @@ static int get_cert_name_hashed(const char *name, char *buf, int buf_len)
158 157
 	return 0;
159 158
 }
160 159
 
160
+static int stirshaken_handle_cache_to_disk(X509 *x, STACK_OF(X509) *xchain, const char *cert_full_path)
161
+{
162
+    int i = 0;
163
+    int w = 0;
164
+    FILE *fp = NULL;
165
+    X509 *xc = NULL;
166
+
167
+    if (!x) {
168
+        LM_ERR("Refusing to save an empty cert\n");
169
+        return -1;
170
+    }
171
+
172
+    fp = fopen(cert_full_path, "w");
173
+    if (!fp) {
174
+        LM_ERR("Failed to create file: %s", cert_full_path);
175
+		return -1;
176
+    }
177
+
178
+    w = PEM_write_X509(fp, x);
179
+	if (w == 0) {
180
+		LM_ERR("Failed to write cert to %s", cert_full_path);
181
+		return -1;
182
+	}
183
+
184
+    for (i = 0; i < sk_X509_num(xchain); i++) {
185
+		xc = sk_X509_value(xchain, i);
186
+		if (!xc) continue;
187
+		w = PEM_write_X509(fp, xc);
188
+		if (w == 0) {
189
+			LM_ERR("Failed to write chain to %s", cert_full_path);
190
+			return -1;
191
+		}
192
+	}
193
+
194
+    if (fp) fclose(fp);
195
+    fp = NULL;
196
+
197
+    return 0;
198
+}
199
+
200
+static int stirshaken_handle_cache_from_disk(stir_shaken_context_t *ss, stir_shaken_cert_t *cert, const char *name)
201
+{
202
+    FILE *fp = NULL;
203
+    X509 *wcert = NULL;
204
+
205
+    LM_DBG("Handle cache from disk; %s", name);
206
+
207
+    if (stir_shaken_zstr(name)) {
208
+        LM_ERR("Cert file name missing");
209
+		return -1;
210
+	}
211
+
212
+    fp = fopen(name, "r");
213
+    if (!fp) {
214
+        LM_ERR("Failed to open %s: %s", name, strerror(errno));
215
+        goto fail;
216
+    }
217
+
218
+    cert->xchain = sk_X509_new_null();
219
+
220
+    while ((wcert = PEM_read_X509(fp, NULL, NULL, NULL))) {
221
+		if (!cert->x) {
222
+			cert->x = wcert;
223
+		}
224
+		else {
225
+			sk_X509_push(cert->xchain, wcert);
226
+		}
227
+	}
228
+
229
+	LM_DBG("done reading file, got %d certs and %d chains", cert->x ? 1 : 0, sk_X509_num(cert->xchain));
230
+
231
+    if (!cert->x) {
232
+        LM_ERR("No certificate found in %s", name);
233
+        goto fail;
234
+    }
235
+
236
+    if (fp) fclose(fp);
237
+    fp = NULL;
238
+
239
+    return 0;
240
+
241
+fail:
242
+    if (fp) fclose(fp);
243
+    return -1;
244
+}
245
+
161 246
 static stir_shaken_status_t shaken_callback(stir_shaken_callback_arg_t *arg)
162 247
 {
163 248
 	stir_shaken_context_t ss = { 0 };
... ...
@@ -207,18 +292,18 @@ static stir_shaken_status_t shaken_callback(stir_shaken_callback_arg_t *arg)
207 292
 
208 293
 					diff = now_s - attr.st_mtime;
209 294
 
210
-					LM_DBG("Checking cached certificate against expiration setting of %zus (now is: %zu, file modification timestamp is: %zu, difference is: %zu)\n",
295
+					LM_DBG("Checking cached certificate against expiration setting of %zus (now is: %lu, file modification timestamp is: %lu, difference is: %lu)\n",
211 296
 						stirshaken_vs_cache_expire_s, now_s, attr.st_mtime, diff);
212 297
 
213 298
 					if (diff > stirshaken_vs_cache_expire_s) {
214
-						LM_WARN("Cached certificate %s is behind expiration threshold (%zu > %zu). Need to download new certificate...\n", cert_full_path, diff, stirshaken_vs_cache_expire_s);
299
+						LM_NOTICE("Cached certificate %s is behind expiration threshold (%lu > %zu). Need to download new certificate...\n", cert_full_path, diff, stirshaken_vs_cache_expire_s);
215 300
 						goto exit;
216 301
 					} else {
217
-						LM_WARN("Cached certificate %s is valid for next %zus\n", cert_full_path, stirshaken_vs_cache_expire_s - diff);
302
+						LM_NOTICE("Cached certificate %s is valid for next %lus\n", cert_full_path, stirshaken_vs_cache_expire_s - diff);
218 303
 					}
219 304
 				}
220 305
 
221
-				if (!(cache_copy.x = stir_shaken_load_x509_from_file(&ss, cert_full_path))) {
306
+				if (-1 == stirshaken_handle_cache_from_disk(&ss, &cache_copy, cert_full_path)) {
222 307
 					LM_ERR("Cannot load X509 from file %s\n", cert_full_path);
223 308
 					goto exit;
224 309
 				}
... ...
@@ -445,8 +530,8 @@ static int stirshaken_handle_cache(stir_shaken_context_t *ss, stir_shaken_passpo
445 530
 
446 531
 		LM_DBG("Saving fresh certificate %s in cache (with name: %s)...\n", x5u, cert_full_path);
447 532
 
448
-		if (STIR_SHAKEN_STATUS_OK != stir_shaken_x509_to_disk(ss, cert->x, cert_full_path)) {
449
-			LM_ERR("Failed to write cert %s to disk (as: %s)", x5u, cert_full_path);
533
+		if (-1 == stirshaken_handle_cache_to_disk(cert->x, cert->xchain, cert_full_path)) {
534
+			LM_ERR("Failed to cache certificate %s to disk", x5u);
450 535
 		}
451 536
 
452 537
 	} else {
... ...
@@ -485,7 +570,8 @@ static int ki_stirshaken_check_identity(sip_msg_t *msg)
485 570
 	ibody = hf->body;
486 571
 
487 572
 	if (STIR_SHAKEN_STATUS_OK != stir_shaken_vs_sih_verify(&ss, vs, ibody.s, &cert_out, &passport_out)) {
488
-		LM_ERR("SIP Identity Header did not pass verification\n");
573
+		LM_ERR("SIP Identity Header did not pass verification: %s", stir_shaken_get_error(&ss, NULL));
574
+
489 575
 		stirshaken_print_error_details(&ss);
490 576
 		goto fail;
491 577
 	}