|
1 |
| -/* $OpenBSD: filemode.c,v 1.66 2025/07/20 12:00:49 tb Exp $ */ |
| 1 | +/* $OpenBSD: filemode.c,v 1.67 2025/08/01 16:33:58 tb Exp $ */ |
2 | 2 | /*
|
3 | 3 | * Copyright (c) 2019 Claudio Jeker <[email protected]>
|
4 | 4 | * Copyright (c) 2019 Kristaps Dzonsons <[email protected]>
|
|
32 | 32 | #include <imsg.h>
|
33 | 33 |
|
34 | 34 | #include <openssl/asn1.h>
|
| 35 | +#include <openssl/cms.h> |
35 | 36 | #include <openssl/err.h>
|
36 | 37 | #include <openssl/evp.h>
|
37 | 38 | #include <openssl/pem.h>
|
@@ -329,6 +330,80 @@ print_signature_path(const char *crl, const char *aia, const struct auth *a)
|
329 | 330 | }
|
330 | 331 | }
|
331 | 332 |
|
| 333 | +/* |
| 334 | + * Attempt to determine the file type from the DER by trial and error. |
| 335 | + */ |
| 336 | +static enum rtype |
| 337 | +rtype_from_der(const char *fn, const unsigned char *der, size_t len) |
| 338 | +{ |
| 339 | + CMS_ContentInfo *cms = NULL; |
| 340 | + X509 *x509 = NULL; |
| 341 | + X509_CRL *crl = NULL; |
| 342 | + const unsigned char *p; |
| 343 | + enum rtype rtype = RTYPE_INVALID; |
| 344 | + |
| 345 | + /* Does der parse as a CMS signed object? */ |
| 346 | + p = der; |
| 347 | + if ((cms = d2i_CMS_ContentInfo(NULL, &p, len)) != NULL) { |
| 348 | + const ASN1_OBJECT *obj; |
| 349 | + |
| 350 | + if (CMS_get0_SignerInfos(cms) == NULL) { |
| 351 | + warnx("%s: CMS object not signedData", fn); |
| 352 | + goto out; |
| 353 | + } |
| 354 | + |
| 355 | + if ((obj = CMS_get0_eContentType(cms)) == NULL) { |
| 356 | + warnx("%s: RFC 6488, section 2.1.3.1: eContentType: " |
| 357 | + "OID object is NULL", fn); |
| 358 | + goto out; |
| 359 | + } |
| 360 | + |
| 361 | + if (OBJ_cmp(obj, aspa_oid) == 0) |
| 362 | + rtype = RTYPE_ASPA; |
| 363 | + else if (OBJ_cmp(obj, mft_oid) == 0) |
| 364 | + rtype = RTYPE_MFT; |
| 365 | + else if (OBJ_cmp(obj, gbr_oid) == 0) |
| 366 | + rtype = RTYPE_GBR; |
| 367 | + else if (OBJ_cmp(obj, roa_oid) == 0) |
| 368 | + rtype = RTYPE_ROA; |
| 369 | + else if (OBJ_cmp(obj, rsc_oid) == 0) |
| 370 | + rtype = RTYPE_RSC; |
| 371 | + else if (OBJ_cmp(obj, spl_oid) == 0) |
| 372 | + rtype = RTYPE_SPL; |
| 373 | + else if (OBJ_cmp(obj, tak_oid) == 0) |
| 374 | + rtype = RTYPE_TAK; |
| 375 | + |
| 376 | + goto out; |
| 377 | + } |
| 378 | + |
| 379 | + /* Does der parse as a certificate? */ |
| 380 | + p = der; |
| 381 | + if ((x509 = d2i_X509(NULL, &p, len)) != NULL) { |
| 382 | + rtype = RTYPE_CER; |
| 383 | + goto out; |
| 384 | + } |
| 385 | + |
| 386 | + /* Does der parse as a CRL? */ |
| 387 | + p = der; |
| 388 | + if ((crl = d2i_X509_CRL(NULL, &p, len)) != NULL) { |
| 389 | + rtype = RTYPE_CRL; |
| 390 | + goto out; |
| 391 | + } |
| 392 | + |
| 393 | + /* |
| 394 | + * We could add some heuristics for recognizing TALs and geofeed by |
| 395 | + * looking for things like "rsync://" and "MII" or "RPKI Signature" |
| 396 | + * using memmem(3). If we do this, we should also rename the function. |
| 397 | + */ |
| 398 | + |
| 399 | + out: |
| 400 | + CMS_ContentInfo_free(cms); |
| 401 | + X509_free(x509); |
| 402 | + X509_CRL_free(crl); |
| 403 | + |
| 404 | + return rtype; |
| 405 | +} |
| 406 | + |
332 | 407 | /*
|
333 | 408 | * Parse file passed with -f option.
|
334 | 409 | */
|
@@ -394,6 +469,8 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
|
394 | 469 | free(hash);
|
395 | 470 |
|
396 | 471 | type = rtype_from_file_extension(file);
|
| 472 | + if (type == RTYPE_INVALID) |
| 473 | + type = rtype_from_der(file, buf, len); |
397 | 474 |
|
398 | 475 | switch (type) {
|
399 | 476 | case RTYPE_ASPA:
|
|
0 commit comments