This commit is contained in:
purplerain 2023-06-24 02:57:55 +00:00
parent be633fa56a
commit 82bafdd0b3
Signed by: purplerain
GPG Key ID: F42C07F07E2E35B7
18 changed files with 514 additions and 213 deletions

View File

@ -30,9 +30,9 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE. .\" SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: malloc.3,v 1.134 2023/06/22 11:04:16 otto Exp $ .\" $OpenBSD: malloc.3,v 1.135 2023/06/23 05:26:45 otto Exp $
.\" .\"
.Dd $Mdocdate: June 22 2023 $ .Dd $Mdocdate: June 23 2023 $
.Dt MALLOC 3 .Dt MALLOC 3
.Os .Os
.Sh NAME .Sh NAME
@ -294,17 +294,6 @@ To record the dump:
To view the leak report: To view the leak report:
.Pp .Pp
.Dl $ kdump -u malloc ... .Dl $ kdump -u malloc ...
.Pp
By default, the immediate caller of a
.Nm
function will be recorded.
Use malloc options
.Cm 2
or
.Cm 3
to record the caller one or two stack frames deeper instead.
These malloc options imply
.Cm D .
.It Cm F .It Cm F
.Dq Freecheck . .Dq Freecheck .
Enable more extensive double free and use after free detection. Enable more extensive double free and use after free detection.
@ -824,14 +813,3 @@ and
.Fn realloc .Fn realloc
to avoid these problems on to avoid these problems on
.Ox . .Ox .
.Pp
The mechanism to record caller functions when using malloc options
.Cm 2
or
.Cm 3
is not guaranteed to work for all platforms, compilers or compilation
options,
and might even crash your program.
Use
.Em only
for debugging purposes.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: malloc.c,v 1.287 2023/06/22 11:04:16 otto Exp $ */ /* $OpenBSD: malloc.c,v 1.288 2023/06/23 05:26:45 otto Exp $ */
/* /*
* Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net> * Copyright (c) 2008, 2010, 2011, 2016, 2023 Otto Moerbeek <otto@drijf.net>
* Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org> * Copyright (c) 2012 Matthew Dempsky <matthew@openbsd.org>
@ -255,11 +255,7 @@ void malloc_dump(void);
PROTO_NORMAL(malloc_dump); PROTO_NORMAL(malloc_dump);
static void malloc_exit(void); static void malloc_exit(void);
#endif #endif
#define CALLER ( \ #define CALLER (DO_STATS ? __builtin_return_address(0) : NULL)
DO_STATS == 0 ? NULL : (__builtin_extract_return_addr( \
DO_STATS == 1 ? __builtin_return_address(0) : \
DO_STATS == 2 ? __builtin_return_address(1) : \
DO_STATS == 3 ? __builtin_return_address(2) : NULL)))
/* low bits of r->p determine size: 0 means >= page size and r->size holding /* low bits of r->p determine size: 0 means >= page size and r->size holding
* real size, otherwise low bits is the bucket + 1 * real size, otherwise low bits is the bucket + 1
@ -369,15 +365,8 @@ omalloc_parseopt(char opt)
mopts.malloc_stats = 0; mopts.malloc_stats = 0;
break; break;
case 'D': case 'D':
case '1':
mopts.malloc_stats = 1; mopts.malloc_stats = 1;
break; break;
case '2':
mopts.malloc_stats = 2;
break;
case '3':
mopts.malloc_stats = 3;
break;
#endif /* MALLOC_STATS */ #endif /* MALLOC_STATS */
case 'f': case 'f':
mopts.malloc_freecheck = 0; mopts.malloc_freecheck = 0;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: bn_convert.c,v 1.9 2023/05/28 10:34:17 jsing Exp $ */ /* $OpenBSD: bn_convert.c,v 1.12 2023/06/23 10:48:40 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved. * All rights reserved.
* *
@ -281,7 +281,7 @@ BN_asc2bn(BIGNUM **bnp, const char *s)
return 0; return 0;
} }
/* Try parsing as hexidecimal with a 0x prefix. */ /* Try parsing as hexadecimal with a 0x prefix. */
CBS_dup(&cbs, &cbs_hex); CBS_dup(&cbs, &cbs_hex);
if (!CBS_get_u8(&cbs_hex, &v)) if (!CBS_get_u8(&cbs_hex, &v))
goto decimal; goto decimal;
@ -291,16 +291,17 @@ BN_asc2bn(BIGNUM **bnp, const char *s)
goto decimal; goto decimal;
if (v != 'X' && v != 'x') if (v != 'X' && v != 'x')
goto decimal; goto decimal;
if (!bn_hex2bn_cbs(bnp, &cbs_hex)) if (bn_hex2bn_cbs(bnp, &cbs_hex) == 0)
return 0; return 0;
goto done; goto done;
decimal: decimal:
if (!bn_dec2bn_cbs(bnp, &cbs)) if (bn_dec2bn_cbs(bnp, &cbs) == 0)
return 0; return 0;
done: done:
if (bnp != NULL && *bnp != NULL)
BN_set_negative(*bnp, neg); BN_set_negative(*bnp, neg);
return 1; return 1;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ec_print.c,v 1.11 2023/03/08 05:45:31 jsing Exp $ */ /* $OpenBSD: ec_print.c,v 1.12 2023/06/23 10:34:16 tb Exp $ */
/* ==================================================================== /* ====================================================================
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved. * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
* *
@ -167,7 +167,7 @@ EC_POINT_hex2point(const EC_GROUP *group, const char *buf,
EC_POINT *ret = NULL; EC_POINT *ret = NULL;
BIGNUM *tmp_bn = NULL; BIGNUM *tmp_bn = NULL;
if (!BN_hex2bn(&tmp_bn, buf)) if (BN_hex2bn(&tmp_bn, buf) == 0)
return NULL; return NULL;
ret = EC_POINT_bn2point(group, tmp_bn, point, ctx); ret = EC_POINT_bn2point(group, tmp_bn, point, ctx);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: x509_set.c,v 1.25 2023/04/25 10:18:39 job Exp $ */ /* $OpenBSD: x509_set.c,v 1.26 2023/06/23 08:00:28 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved. * All rights reserved.
* *
@ -106,7 +106,7 @@ X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial)
ASN1_INTEGER *in; ASN1_INTEGER *in;
if (x == NULL) if (x == NULL)
return (0); return 0;
in = x->cert_info->serialNumber; in = x->cert_info->serialNumber;
if (in != serial) { if (in != serial) {
in = ASN1_INTEGER_dup(serial); in = ASN1_INTEGER_dup(serial);
@ -116,17 +116,17 @@ X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial)
x->cert_info->serialNumber = in; x->cert_info->serialNumber = in;
} }
} }
return (in != NULL); return in != NULL;
} }
LCRYPTO_ALIAS(X509_set_serialNumber); LCRYPTO_ALIAS(X509_set_serialNumber);
int int
X509_set_issuer_name(X509 *x, X509_NAME *name) X509_set_issuer_name(X509 *x, X509_NAME *name)
{ {
if ((x == NULL) || (x->cert_info == NULL)) if (x == NULL || x->cert_info == NULL)
return (0); return 0;
x->cert_info->enc.modified = 1; x->cert_info->enc.modified = 1;
return (X509_NAME_set(&x->cert_info->issuer, name)); return X509_NAME_set(&x->cert_info->issuer, name);
} }
LCRYPTO_ALIAS(X509_set_issuer_name); LCRYPTO_ALIAS(X509_set_issuer_name);
@ -134,9 +134,9 @@ int
X509_set_subject_name(X509 *x, X509_NAME *name) X509_set_subject_name(X509 *x, X509_NAME *name)
{ {
if (x == NULL || x->cert_info == NULL) if (x == NULL || x->cert_info == NULL)
return (0); return 0;
x->cert_info->enc.modified = 1; x->cert_info->enc.modified = 1;
return (X509_NAME_set(&x->cert_info->subject, name)); return X509_NAME_set(&x->cert_info->subject, name);
} }
LCRYPTO_ALIAS(X509_set_subject_name); LCRYPTO_ALIAS(X509_set_subject_name);
@ -151,7 +151,7 @@ ASN1_TIME *
X509_getm_notBefore(const X509 *x) X509_getm_notBefore(const X509 *x)
{ {
if (x == NULL || x->cert_info == NULL || x->cert_info->validity == NULL) if (x == NULL || x->cert_info == NULL || x->cert_info->validity == NULL)
return (NULL); return NULL;
return x->cert_info->validity->notBefore; return x->cert_info->validity->notBefore;
} }
LCRYPTO_ALIAS(X509_getm_notBefore); LCRYPTO_ALIAS(X509_getm_notBefore);
@ -162,7 +162,7 @@ X509_set_notBefore(X509 *x, const ASN1_TIME *tm)
ASN1_TIME *in; ASN1_TIME *in;
if (x == NULL || x->cert_info->validity == NULL) if (x == NULL || x->cert_info->validity == NULL)
return (0); return 0;
in = x->cert_info->validity->notBefore; in = x->cert_info->validity->notBefore;
if (in != tm) { if (in != tm) {
in = ASN1_STRING_dup(tm); in = ASN1_STRING_dup(tm);
@ -172,7 +172,7 @@ X509_set_notBefore(X509 *x, const ASN1_TIME *tm)
x->cert_info->validity->notBefore = in; x->cert_info->validity->notBefore = in;
} }
} }
return (in != NULL); return in != NULL;
} }
LCRYPTO_ALIAS(X509_set_notBefore); LCRYPTO_ALIAS(X509_set_notBefore);
@ -194,7 +194,7 @@ ASN1_TIME *
X509_getm_notAfter(const X509 *x) X509_getm_notAfter(const X509 *x)
{ {
if (x == NULL || x->cert_info == NULL || x->cert_info->validity == NULL) if (x == NULL || x->cert_info == NULL || x->cert_info->validity == NULL)
return (NULL); return NULL;
return x->cert_info->validity->notAfter; return x->cert_info->validity->notAfter;
} }
LCRYPTO_ALIAS(X509_getm_notAfter); LCRYPTO_ALIAS(X509_getm_notAfter);
@ -205,7 +205,7 @@ X509_set_notAfter(X509 *x, const ASN1_TIME *tm)
ASN1_TIME *in; ASN1_TIME *in;
if (x == NULL || x->cert_info->validity == NULL) if (x == NULL || x->cert_info->validity == NULL)
return (0); return 0;
in = x->cert_info->validity->notAfter; in = x->cert_info->validity->notAfter;
if (in != tm) { if (in != tm) {
in = ASN1_STRING_dup(tm); in = ASN1_STRING_dup(tm);
@ -215,7 +215,7 @@ X509_set_notAfter(X509 *x, const ASN1_TIME *tm)
x->cert_info->validity->notAfter = in; x->cert_info->validity->notAfter = in;
} }
} }
return (in != NULL); return in != NULL;
} }
LCRYPTO_ALIAS(X509_set_notAfter); LCRYPTO_ALIAS(X509_set_notAfter);
@ -229,10 +229,10 @@ LCRYPTO_ALIAS(X509_set1_notAfter);
int int
X509_set_pubkey(X509 *x, EVP_PKEY *pkey) X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
{ {
if ((x == NULL) || (x->cert_info == NULL)) if (x == NULL || x->cert_info == NULL)
return (0); return 0;
x->cert_info->enc.modified = 1; x->cert_info->enc.modified = 1;
return (X509_PUBKEY_set(&(x->cert_info->key), pkey)); return X509_PUBKEY_set(&x->cert_info->key, pkey);
} }
LCRYPTO_ALIAS(X509_set_pubkey); LCRYPTO_ALIAS(X509_set_pubkey);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: bn_convert.c,v 1.2 2023/05/27 15:50:56 jsing Exp $ */ /* $OpenBSD: bn_convert.c,v 1.3 2023/06/23 10:50:47 tb Exp $ */
/* /*
* Copyright (c) 2023 Joel Sing <jsing@openbsd.org> * Copyright (c) 2023 Joel Sing <jsing@openbsd.org>
* *
@ -214,6 +214,16 @@ test_bn_asc2bn(void)
} }
} }
/*
* While it makes little sense to call BN_asc2bn() with a NULL bn,
* check for consistent behavior.
*/
if (!BN_asc2bn(NULL, "1") || !BN_asc2bn(NULL, "-1") ||
!BN_asc2bn(NULL, "0x1") || !BN_asc2bn(NULL, "-0x1")) {
fprintf(stderr, "FAIL: BN_asc2bn() with NULL BIGNUM failed\n");
goto failure;
}
failed = 0; failed = 0;
failure: failure:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ksmn.c,v 1.7 2022/04/25 16:17:19 claudio Exp $ */ /* $OpenBSD: ksmn.c,v 1.8 2023/06/23 03:47:10 mlarkin Exp $ */
/* /*
* Copyright (c) 2019 Bryan Steele <brynet@openbsd.org> * Copyright (c) 2019 Bryan Steele <brynet@openbsd.org>
@ -105,6 +105,7 @@ static const struct pci_matchid ksmn_devices[] = {
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_1X_RC }, { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_1X_RC },
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_3X_RC }, { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_3X_RC },
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_6X_RC }, { PCI_VENDOR_AMD, PCI_PRODUCT_AMD_17_6X_RC },
{ PCI_VENDOR_AMD, PCI_PRODUCT_AMD_19_6X_RC },
}; };
int int
@ -172,6 +173,9 @@ ksmn_attach(struct device *parent, struct device *self, void *aux)
(m >= 0xa0 && m <= 0xaf)) (m >= 0xa0 && m <= 0xaf))
sc->sc_ccd_offset = 0x300; sc->sc_ccd_offset = 0x300;
if (m >= 0x60 && m <= 0x6f)
sc->sc_ccd_offset = 0x308;
if ((m >= 0x10 && m <= 0x1f) || if ((m >= 0x10 && m <= 0x1f) ||
(m >= 0xa0 && m <= 0xaf)) (m >= 0xa0 && m <= 0xaf))
ksmn_ccd_attach(sc, 12); ksmn_ccd_attach(sc, 12);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: uipc_mbuf.c,v 1.286 2023/05/16 20:09:27 mvs Exp $ */ /* $OpenBSD: uipc_mbuf.c,v 1.287 2023/06/23 04:36:49 gnezdo Exp $ */
/* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */
/* /*
@ -214,7 +214,7 @@ nmbclust_update(long newval)
{ {
int i; int i;
if (newval < 0 || newval > LONG_MAX / MCLBYTES) if (newval <= 0 || newval > LONG_MAX / MCLBYTES)
return ERANGE; return ERANGE;
/* update the global mbuf memory limit */ /* update the global mbuf memory limit */
nmbclust = newval; nmbclust = newval;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ex.c,v 1.22 2022/02/20 19:45:51 tb Exp $ */ /* $OpenBSD: ex.c,v 1.23 2023/06/23 15:06:45 millert Exp $ */
/*- /*-
* Copyright (c) 1992, 1993, 1994 * Copyright (c) 1992, 1993, 1994
@ -1454,8 +1454,14 @@ addr_verify:
LF_INIT(FL_ISSET(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT)); LF_INIT(FL_ISSET(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT));
if (!LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT | E_NOAUTO) && if (!LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT | E_NOAUTO) &&
!F_ISSET(sp, SC_EX_GLOBAL) && !F_ISSET(sp, SC_EX_GLOBAL) &&
O_ISSET(sp, O_AUTOPRINT) && F_ISSET(ecp, E_AUTOPRINT)) O_ISSET(sp, O_AUTOPRINT) && F_ISSET(ecp, E_AUTOPRINT)) {
/* Honor the number option if autoprint is set. */
if (F_ISSET(ecp, E_OPTNUM))
LF_INIT(E_C_HASH);
else
LF_INIT(E_C_PRINT); LF_INIT(E_C_PRINT);
}
if (LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT)) { if (LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT)) {
cur.lno = sp->lno; cur.lno = sp->lno;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ex_subst.c,v 1.30 2017/04/18 01:45:35 deraadt Exp $ */ /* $OpenBSD: ex_subst.c,v 1.31 2023/06/23 15:06:45 millert Exp $ */
/*- /*-
* Copyright (c) 1992, 1993, 1994 * Copyright (c) 1992, 1993, 1994
@ -633,7 +633,9 @@ nextmatch: match[0].rm_so = offset;
goto lquit; goto lquit;
} }
} else { } else {
if (ex_print(sp, cmdp, &from, &to, 0) || const int flags =
O_ISSET(sp, O_NUMBER) ? E_C_HASH : 0;
if (ex_print(sp, cmdp, &from, &to, flags) ||
ex_scprint(sp, &from, &to)) ex_scprint(sp, &from, &to))
goto lquit; goto lquit;
if (ex_txt(sp, &tiq, 0, TXT_CR)) if (ex_txt(sp, &tiq, 0, TXT_CR))

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cert.c,v 1.109 2023/06/20 12:28:08 job Exp $ */ /* $OpenBSD: cert.c,v 1.112 2023/06/23 20:05:30 tb Exp $ */
/* /*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org> * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2021 Job Snijders <job@openbsd.org> * Copyright (c) 2021 Job Snijders <job@openbsd.org>
@ -204,6 +204,11 @@ sbgp_assysnum(struct parse *p, X509_EXTENSION *ext)
goto out; goto out;
} }
if (asz == 0) {
warnx("%s: RFC 6487 section 4.8.11: empty asIdsOrRanges",
p->fn);
goto out;
}
if (asz >= MAX_AS_SIZE) { if (asz >= MAX_AS_SIZE) {
warnx("%s: too many AS number entries: limit %d", warnx("%s: too many AS number entries: limit %d",
p->fn, MAX_AS_SIZE); p->fn, MAX_AS_SIZE);
@ -371,6 +376,11 @@ sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
p->fn, af->ipAddressChoice->type); p->fn, af->ipAddressChoice->type);
goto out; goto out;
} }
if (ipsz == p->res->ipsz) {
warnx("%s: RFC 6487 section 4.8.10: "
"empty ipAddressesOrRanges", p->fn);
goto out;
}
if (ipsz >= MAX_IP_SIZE) if (ipsz >= MAX_IP_SIZE)
goto out; goto out;
@ -412,6 +422,11 @@ sbgp_ipaddrblk(struct parse *p, X509_EXTENSION *ext)
} }
} }
if (p->res->ipsz == 0) {
warnx("%s: RFC 6487 section 4.8.10: empty ipAddrBlock", p->fn);
goto out;
}
rc = 1; rc = 1;
out: out:
sk_IPAddressFamily_pop_free(addrblk, IPAddressFamily_free); sk_IPAddressFamily_pop_free(addrblk, IPAddressFamily_free);
@ -648,7 +663,6 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
{ {
const unsigned char *oder; const unsigned char *oder;
int extsz; int extsz;
int sia_present = 0;
size_t i; size_t i;
X509 *x = NULL; X509 *x = NULL;
X509_EXTENSION *ext = NULL; X509_EXTENSION *ext = NULL;
@ -658,7 +672,10 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
ASN1_OBJECT *obj; ASN1_OBJECT *obj;
EVP_PKEY *pkey; EVP_PKEY *pkey;
struct parse p; struct parse p;
int nid; int nid, ip, as, sia, cp, crldp, aia, aki, ski,
eku, bc, ku;
nid = ip = as = sia = cp = crldp = aia = aki = ski = eku = bc = ku = 0;
/* just fail for empty buffers, the warning was printed elsewhere */ /* just fail for empty buffers, the warning was printed elsewhere */
if (der == NULL) if (der == NULL)
@ -721,38 +738,58 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
obj = X509_EXTENSION_get_object(ext); obj = X509_EXTENSION_get_object(ext);
assert(obj != NULL); assert(obj != NULL);
switch (OBJ_obj2nid(obj)) { switch ((nid = OBJ_obj2nid(obj))) {
case NID_sbgp_ipAddrBlock: case NID_sbgp_ipAddrBlock:
if (ip++ >= 1)
goto dup;
if (!sbgp_ipaddrblk(&p, ext)) if (!sbgp_ipaddrblk(&p, ext))
goto out; goto out;
break; break;
case NID_sbgp_autonomousSysNum: case NID_sbgp_autonomousSysNum:
if (as++ > 0)
goto dup;
if (!sbgp_assysnum(&p, ext)) if (!sbgp_assysnum(&p, ext))
goto out; goto out;
break; break;
case NID_sinfo_access: case NID_sinfo_access:
sia_present = 1; if (sia++ > 0)
goto dup;
if (!sbgp_sia(&p, ext)) if (!sbgp_sia(&p, ext))
goto out; goto out;
break; break;
case NID_certificate_policies: case NID_certificate_policies:
if (cp++ > 0)
goto dup;
if (!certificate_policies(&p, ext)) if (!certificate_policies(&p, ext))
goto out; goto out;
break; break;
case NID_crl_distribution_points: case NID_crl_distribution_points:
/* ignored here, handled later */ if (crldp++ > 0)
goto dup;
break; break;
case NID_info_access: case NID_info_access:
if (aia++ > 0)
goto dup;
break; break;
case NID_authority_key_identifier: case NID_authority_key_identifier:
if (aki++ > 0)
goto dup;
break; break;
case NID_subject_key_identifier: case NID_subject_key_identifier:
if (ski++ > 0)
goto dup;
break; break;
case NID_ext_key_usage: case NID_ext_key_usage:
if (eku++ > 0)
goto dup;
break; break;
case NID_basic_constraints: case NID_basic_constraints:
if (bc++ > 0)
goto dup;
break; break;
case NID_key_usage: case NID_key_usage:
if (ku++ > 0)
goto dup;
break; break;
default: default:
/* unexpected extensions warrant investigation */ /* unexpected extensions warrant investigation */
@ -831,7 +868,7 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
goto out; goto out;
} }
} }
if (sia_present) { if (sia) {
warnx("%s: unexpected SIA extension in BGPsec cert", warnx("%s: unexpected SIA extension in BGPsec cert",
p.fn); p.fn);
goto out; goto out;
@ -850,6 +887,9 @@ cert_parse_pre(const char *fn, const unsigned char *der, size_t len)
p.res->x509 = x; p.res->x509 = x;
return p.res; return p.res;
dup:
warnx("%s: RFC 5280 section 4.2: duplicate %s extension", fn,
OBJ_nid2sn(nid));
out: out:
cert_free(p.res); cert_free(p.res);
X509_free(x); X509_free(x);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: extern.h,v 1.184 2023/06/07 10:46:34 job Exp $ */ /* $OpenBSD: extern.h,v 1.185 2023/06/23 11:36:24 claudio Exp $ */
/* /*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
* *
@ -486,6 +486,9 @@ enum rrdp_msg {
RRDP_ABORT, RRDP_ABORT,
}; };
/* Maximum number of delta files per RRDP notification file. */
#define MAX_RRDP_DELTAS 300
/* /*
* RRDP session state, needed to pickup at the right spot on next run. * RRDP session state, needed to pickup at the right spot on next run.
*/ */
@ -493,6 +496,7 @@ struct rrdp_session {
char *last_mod; char *last_mod;
char *session_id; char *session_id;
long long serial; long long serial;
char *deltas[MAX_RRDP_DELTAS];
}; };
/* /*
@ -759,7 +763,11 @@ void proc_rrdp(int) __attribute__((noreturn));
/* Repository handling */ /* Repository handling */
int filepath_add(struct filepath_tree *, char *, time_t); int filepath_add(struct filepath_tree *, char *, time_t);
void rrdp_clear(unsigned int); void rrdp_clear(unsigned int);
void rrdp_save_state(unsigned int, struct rrdp_session *); void rrdp_session_save(unsigned int, struct rrdp_session *);
void rrdp_session_free(struct rrdp_session *);
void rrdp_session_buffer(struct ibuf *,
const struct rrdp_session *);
struct rrdp_session *rrdp_session_read(struct ibuf *);
int rrdp_handle_file(unsigned int, enum publish_type, char *, int rrdp_handle_file(unsigned int, enum publish_type, char *,
char *, size_t, char *, size_t); char *, size_t, char *, size_t);
char *repo_basedir(const struct repo *, int); char *repo_basedir(const struct repo *, int);
@ -944,9 +952,6 @@ int mkpathat(int, const char *);
/* Maximum number of delegated hosting locations (repositories) for each TAL. */ /* Maximum number of delegated hosting locations (repositories) for each TAL. */
#define MAX_REPO_PER_TAL 1000 #define MAX_REPO_PER_TAL 1000
/* Maximum number of delta files per RRDP notification file. */
#define MAX_RRDP_DELTAS 300
/* /*
* Time - Evaluation time is used as the current time if it is * Time - Evaluation time is used as the current time if it is
* larger than X509_TIME_MIN, otherwise the system time is used. * larger than X509_TIME_MIN, otherwise the system time is used.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: main.c,v 1.242 2023/06/20 15:15:14 claudio Exp $ */ /* $OpenBSD: main.c,v 1.243 2023/06/23 11:36:24 claudio Exp $ */
/* /*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -280,9 +280,8 @@ rrdp_fetch(unsigned int id, const char *uri, const char *local,
io_simple_buffer(b, &id, sizeof(id)); io_simple_buffer(b, &id, sizeof(id));
io_str_buffer(b, local); io_str_buffer(b, local);
io_str_buffer(b, uri); io_str_buffer(b, uri);
io_str_buffer(b, s->session_id);
io_simple_buffer(b, &s->serial, sizeof(s->serial)); rrdp_session_buffer(b, s);
io_str_buffer(b, s->last_mod);
io_close_buffer(&rrdpq, b); io_close_buffer(&rrdpq, b);
} }
@ -679,7 +678,7 @@ rrdp_process(struct ibuf *b)
{ {
enum rrdp_msg type; enum rrdp_msg type;
enum publish_type pt; enum publish_type pt;
struct rrdp_session s; struct rrdp_session *s;
char *uri, *last_mod, *data; char *uri, *last_mod, *data;
char hash[SHA256_DIGEST_LENGTH]; char hash[SHA256_DIGEST_LENGTH];
size_t dsz; size_t dsz;
@ -700,12 +699,9 @@ rrdp_process(struct ibuf *b)
rrdp_http_fetch(id, uri, last_mod); rrdp_http_fetch(id, uri, last_mod);
break; break;
case RRDP_SESSION: case RRDP_SESSION:
io_read_str(b, &s.session_id); s = rrdp_session_read(b);
io_read_buf(b, &s.serial, sizeof(s.serial)); rrdp_session_save(id, s);
io_read_str(b, &s.last_mod); rrdp_session_free(s);
rrdp_save_state(id, &s);
free(s.session_id);
free(s.last_mod);
break; break;
case RRDP_FILE: case RRDP_FILE:
io_read_buf(b, &pt, sizeof(pt)); io_read_buf(b, &pt, sizeof(pt));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: repo.c,v 1.47 2023/05/30 16:02:28 job Exp $ */ /* $OpenBSD: repo.c,v 1.48 2023/06/23 11:36:24 claudio Exp $ */
/* /*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -619,22 +619,26 @@ repo_alloc(int talid)
* Parse the RRDP state file if it exists and set the session struct * Parse the RRDP state file if it exists and set the session struct
* based on that information. * based on that information.
*/ */
static void static struct rrdp_session *
rrdp_parse_state(const struct rrdprepo *rr, struct rrdp_session *state) rrdp_session_parse(const struct rrdprepo *rr)
{ {
FILE *f; FILE *f;
int fd, ln = 0; struct rrdp_session *state;
int fd, ln = 0, deltacnt = 0;
const char *errstr; const char *errstr;
char *line = NULL, *file; char *line = NULL, *file;
size_t len = 0; size_t len = 0;
ssize_t n; ssize_t n;
if ((state = calloc(1, sizeof(*state))) == NULL)
err(1, NULL);
file = rrdp_state_filename(rr, 0); file = rrdp_state_filename(rr, 0);
if ((fd = open(file, O_RDONLY)) == -1) { if ((fd = open(file, O_RDONLY)) == -1) {
if (errno != ENOENT) if (errno != ENOENT)
warn("%s: open state file", rr->basedir); warn("%s: open state file", rr->basedir);
free(file); free(file);
return; return state;
} }
free(file); free(file);
f = fdopen(fd, "r"); f = fdopen(fd, "r");
@ -655,39 +659,47 @@ rrdp_parse_state(const struct rrdprepo *rr, struct rrdp_session *state)
goto fail; goto fail;
break; break;
case 2: case 2:
if (strcmp(line, "-") == 0)
break;
if ((state->last_mod = strdup(line)) == NULL) if ((state->last_mod = strdup(line)) == NULL)
err(1, NULL); err(1, NULL);
break; break;
default: default:
if (deltacnt >= MAX_RRDP_DELTAS)
goto fail; goto fail;
if ((state->deltas[deltacnt++] = strdup(line)) == NULL)
err(1, NULL);
break;
} }
ln++; ln++;
} }
free(line);
if (ferror(f)) if (ferror(f))
goto fail; goto fail;
fclose(f); fclose(f);
return; free(line);
return state;
fail: fail:
warnx("%s: troubles reading state file", rr->basedir); warnx("%s: troubles reading state file", rr->basedir);
fclose(f); fclose(f);
free(line);
free(state->session_id); free(state->session_id);
free(state->last_mod); free(state->last_mod);
memset(state, 0, sizeof(*state)); memset(state, 0, sizeof(*state));
return state;
} }
/* /*
* Carefully write the RRDP session state file back. * Carefully write the RRDP session state file back.
*/ */
void void
rrdp_save_state(unsigned int id, struct rrdp_session *state) rrdp_session_save(unsigned int id, struct rrdp_session *state)
{ {
struct rrdprepo *rr; struct rrdprepo *rr;
char *temp, *file; char *temp, *file;
FILE *f; FILE *f = NULL;
int fd; int fd, i;
rr = rrdp_find(id); rr = rrdp_find(id);
if (rr == NULL) if (rr == NULL)
@ -696,10 +708,8 @@ rrdp_save_state(unsigned int id, struct rrdp_session *state)
file = rrdp_state_filename(rr, 0); file = rrdp_state_filename(rr, 0);
temp = rrdp_state_filename(rr, 1); temp = rrdp_state_filename(rr, 1);
if ((fd = mkostemp(temp, O_CLOEXEC)) == -1) { if ((fd = mkostemp(temp, O_CLOEXEC)) == -1)
warn("mkostemp %s", temp);
goto fail; goto fail;
}
(void)fchmod(fd, 0644); (void)fchmod(fd, 0644);
f = fdopen(fd, "w"); f = fdopen(fd, "w");
if (f == NULL) if (f == NULL)
@ -707,37 +717,94 @@ rrdp_save_state(unsigned int id, struct rrdp_session *state)
/* write session state file out */ /* write session state file out */
if (fprintf(f, "%s\n%lld\n", state->session_id, if (fprintf(f, "%s\n%lld\n", state->session_id,
state->serial) < 0) { state->serial) < 0)
fclose(f);
goto fail;
}
if (state->last_mod != NULL) {
if (fprintf(f, "%s\n", state->last_mod) < 0) {
fclose(f);
goto fail;
}
}
if (fclose(f) != 0)
goto fail; goto fail;
if (rename(temp, file) == -1) if (state->last_mod != NULL) {
warn("%s: rename state file", rr->basedir); if (fprintf(f, "%s\n", state->last_mod) < 0)
goto fail;
} else {
if (fprintf(f, "-\n") < 0)
goto fail;
}
for (i = 0; state->deltas[i] != NULL; i++) {
if (fprintf(f, "%s\n", state->deltas[i]) < 0)
goto fail;
}
if (fclose(f) != 0) {
f = NULL;
goto fail;
}
if (rename(temp, file) == -1) {
warn("%s: rename %s to %s", rr->basedir, temp, file);
unlink(temp);
}
free(temp); free(temp);
free(file); free(file);
return; return;
fail: fail:
warnx("%s: failed to save state", rr->basedir); warn("%s: save state to %s", rr->basedir, temp);
if (f != NULL)
fclose(f);
unlink(temp); unlink(temp);
free(temp); free(temp);
free(file); free(file);
} }
/*
* Free an rrdp_session pointer. Safe to call with NULL.
*/
void
rrdp_session_free(struct rrdp_session *s)
{
size_t i;
if (s == NULL)
return;
free(s->session_id);
free(s->last_mod);
for (i = 0; i < sizeof(s->deltas) / sizeof(s->deltas[0]); i++)
free(s->deltas[i]);
free(s);
}
void
rrdp_session_buffer(struct ibuf *b, const struct rrdp_session *s)
{
size_t i;
io_str_buffer(b, s->session_id);
io_simple_buffer(b, &s->serial, sizeof(s->serial));
io_str_buffer(b, s->last_mod);
for (i = 0; i < sizeof(s->deltas) / sizeof(s->deltas[0]); i++)
io_str_buffer(b, s->deltas[i]);
}
struct rrdp_session *
rrdp_session_read(struct ibuf *b)
{
struct rrdp_session *s;
size_t i;
if ((s = calloc(1, sizeof(*s))) == NULL)
err(1, NULL);
io_read_str(b, &s->session_id);
io_read_buf(b, &s->serial, sizeof(s->serial));
io_read_str(b, &s->last_mod);
for (i = 0; i < sizeof(s->deltas) / sizeof(s->deltas[0]); i++)
io_read_str(b, &s->deltas[i]);
return s;
}
static struct rrdprepo * static struct rrdprepo *
rrdp_get(const char *uri) rrdp_get(const char *uri)
{ {
struct rrdp_session state = { 0 }; struct rrdp_session *state;
struct rrdprepo *rr; struct rrdprepo *rr;
SLIST_FOREACH(rr, &rrdprepos, entry) SLIST_FOREACH(rr, &rrdprepos, entry)
@ -767,10 +834,9 @@ rrdp_get(const char *uri)
} }
/* parse state and start the sync */ /* parse state and start the sync */
rrdp_parse_state(rr, &state); state = rrdp_session_parse(rr);
rrdp_fetch(rr->id, rr->notifyuri, rr->notifyuri, &state); rrdp_fetch(rr->id, rr->notifyuri, rr->notifyuri, state);
free(state.session_id); rrdp_session_free(state);
free(state.last_mod);
logx("%s: pulling from %s", rr->notifyuri, "network"); logx("%s: pulling from %s", rr->notifyuri, "network");
@ -1795,7 +1861,8 @@ repo_free(void)
} }
/* /*
* Remove all files and directories under base but do not remove base itself. * Remove all files and directories under base.
* Do not remove base directory itself and the .state file.
*/ */
static void static void
remove_contents(char *base) remove_contents(char *base)
@ -1812,6 +1879,9 @@ remove_contents(char *base)
case FTS_NSOK: case FTS_NSOK:
case FTS_SL: case FTS_SL:
case FTS_SLNONE: case FTS_SLNONE:
if (e->fts_level == 1 &&
strcmp(e->fts_name, ".state") == 0)
break;
if (unlink(e->fts_accpath) == -1) if (unlink(e->fts_accpath) == -1)
warn("unlink %s", e->fts_path); warn("unlink %s", e->fts_path);
break; break;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: rrdp.c,v 1.31 2023/06/20 15:15:14 claudio Exp $ */ /* $OpenBSD: rrdp.c,v 1.32 2023/06/23 11:36:24 claudio Exp $ */
/* /*
* Copyright (c) 2020 Nils Fisher <nils_fisher@hotmail.com> * Copyright (c) 2020 Nils Fisher <nils_fisher@hotmail.com>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@ -65,8 +65,8 @@ struct rrdp {
char hash[SHA256_DIGEST_LENGTH]; char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX ctx; SHA256_CTX ctx;
struct rrdp_session repository; struct rrdp_session *repository;
struct rrdp_session current; struct rrdp_session *current;
XML_Parser parser; XML_Parser parser;
struct notification_xml *nxml; struct notification_xml *nxml;
struct snapshot_xml *sxml; struct snapshot_xml *sxml;
@ -135,9 +135,7 @@ rrdp_state_send(struct rrdp *s)
b = io_new_buffer(); b = io_new_buffer();
io_simple_buffer(b, &type, sizeof(type)); io_simple_buffer(b, &type, sizeof(type));
io_simple_buffer(b, &s->id, sizeof(s->id)); io_simple_buffer(b, &s->id, sizeof(s->id));
io_str_buffer(b, s->current.session_id); rrdp_session_buffer(b, s->current);
io_simple_buffer(b, &s->current.serial, sizeof(s->current.serial));
io_str_buffer(b, s->current.last_mod);
io_close_buffer(&msgq, b); io_close_buffer(&msgq, b);
} }
@ -182,8 +180,7 @@ rrdp_publish_file(struct rrdp *s, struct publish_xml *pxml,
} }
static void static void
rrdp_new(unsigned int id, char *local, char *notify, char *session_id, rrdp_new(unsigned int id, char *local, char *notify, struct rrdp_session *state)
long long serial, char *last_mod)
{ {
struct rrdp *s; struct rrdp *s;
@ -194,15 +191,15 @@ rrdp_new(unsigned int id, char *local, char *notify, char *session_id,
s->id = id; s->id = id;
s->local = local; s->local = local;
s->notifyuri = notify; s->notifyuri = notify;
s->repository.session_id = session_id; s->repository = state;
s->repository.serial = serial; if ((s->current = calloc(1, sizeof(*s->current))) == NULL)
s->repository.last_mod = last_mod; err(1, NULL);
s->state = RRDP_STATE_REQ; s->state = RRDP_STATE_REQ;
if ((s->parser = XML_ParserCreate("US-ASCII")) == NULL) if ((s->parser = XML_ParserCreate("US-ASCII")) == NULL)
err(1, "XML_ParserCreate"); err(1, "XML_ParserCreate");
s->nxml = new_notification_xml(s->parser, &s->repository, &s->current, s->nxml = new_notification_xml(s->parser, s->repository, s->current,
notify); notify);
TAILQ_INSERT_TAIL(&states, s, entry); TAILQ_INSERT_TAIL(&states, s, entry);
@ -227,10 +224,8 @@ rrdp_free(struct rrdp *s)
free(s->notifyuri); free(s->notifyuri);
free(s->local); free(s->local);
free(s->last_mod); free(s->last_mod);
free(s->repository.last_mod); rrdp_session_free(s->repository);
free(s->repository.session_id); rrdp_session_free(s->current);
free(s->current.last_mod);
free(s->current.session_id);
free(s); free(s);
} }
@ -259,7 +254,7 @@ rrdp_failed(struct rrdp *s)
free_delta_xml(s->dxml); free_delta_xml(s->dxml);
s->dxml = NULL; s->dxml = NULL;
rrdp_clear_repo(s); rrdp_clear_repo(s);
s->sxml = new_snapshot_xml(s->parser, &s->current, s); s->sxml = new_snapshot_xml(s->parser, s->current, s);
s->task = SNAPSHOT; s->task = SNAPSHOT;
s->state = RRDP_STATE_REQ; s->state = RRDP_STATE_REQ;
logx("%s: delta sync failed, fallback to snapshot", s->local); logx("%s: delta sync failed, fallback to snapshot", s->local);
@ -322,26 +317,26 @@ rrdp_finished(struct rrdp *s)
switch (s->task) { switch (s->task) {
case NOTIFICATION: case NOTIFICATION:
logx("%s: repository not modified (%s#%lld)", logx("%s: repository not modified (%s#%lld)",
s->local, s->repository.session_id, s->local, s->repository->session_id,
s->repository.serial); s->repository->serial);
rrdp_state_send(s); rrdp_state_send(s);
rrdp_free(s); rrdp_free(s);
rrdp_done(id, 1); rrdp_done(id, 1);
break; break;
case SNAPSHOT: case SNAPSHOT:
logx("%s: downloading snapshot (%s#%lld)", logx("%s: downloading snapshot (%s#%lld)",
s->local, s->current.session_id, s->local, s->current->session_id,
s->current.serial); s->current->serial);
rrdp_clear_repo(s); rrdp_clear_repo(s);
s->sxml = new_snapshot_xml(p, &s->current, s); s->sxml = new_snapshot_xml(p, s->current, s);
s->state = RRDP_STATE_REQ; s->state = RRDP_STATE_REQ;
break; break;
case DELTA: case DELTA:
logx("%s: downloading %lld deltas (%s#%lld)", logx("%s: downloading %lld deltas (%s#%lld)",
s->local, s->local,
s->repository.serial - s->current.serial, s->repository->serial - s->current->serial,
s->current.session_id, s->current.serial); s->current->session_id, s->current->serial);
s->dxml = new_delta_xml(p, &s->current, s); s->dxml = new_delta_xml(p, s->current, s);
s->state = RRDP_STATE_REQ; s->state = RRDP_STATE_REQ;
break; break;
} }
@ -360,14 +355,14 @@ rrdp_finished(struct rrdp *s)
} else { } else {
/* reset delta parser for next delta */ /* reset delta parser for next delta */
free_delta_xml(s->dxml); free_delta_xml(s->dxml);
s->dxml = new_delta_xml(p, &s->current, s); s->dxml = new_delta_xml(p, s->current, s);
s->state = RRDP_STATE_REQ; s->state = RRDP_STATE_REQ;
} }
break; break;
} }
} else if (s->res == HTTP_NOT_MOD && s->task == NOTIFICATION) { } else if (s->res == HTTP_NOT_MOD && s->task == NOTIFICATION) {
logx("%s: notification file not modified (%s#%lld)", s->local, logx("%s: notification file not modified (%s#%lld)", s->local,
s->repository.session_id, s->repository.serial); s->repository->session_id, s->repository->serial);
/* no need to update state file */ /* no need to update state file */
rrdp_free(s); rrdp_free(s);
rrdp_done(id, 1); rrdp_done(id, 1);
@ -408,12 +403,12 @@ static void
rrdp_input_handler(int fd) rrdp_input_handler(int fd)
{ {
static struct ibuf *inbuf; static struct ibuf *inbuf;
char *local, *notify, *session_id, *last_mod; struct rrdp_session *state;
char *local, *notify, *last_mod;
struct ibuf *b; struct ibuf *b;
struct rrdp *s; struct rrdp *s;
enum rrdp_msg type; enum rrdp_msg type;
enum http_result res; enum http_result res;
long long serial;
unsigned int id; unsigned int id;
int ok; int ok;
@ -426,15 +421,12 @@ rrdp_input_handler(int fd)
switch (type) { switch (type) {
case RRDP_START: case RRDP_START:
io_read_str(b, &local);
io_read_str(b, &notify);
io_read_str(b, &session_id);
io_read_buf(b, &serial, sizeof(serial));
io_read_str(b, &last_mod);
if (ibuf_fd_avail(b)) if (ibuf_fd_avail(b))
errx(1, "received unexpected fd"); errx(1, "received unexpected fd");
io_read_str(b, &local);
rrdp_new(id, local, notify, session_id, serial, last_mod); io_read_str(b, &notify);
state = rrdp_session_read(b);
rrdp_new(id, local, notify, state);
break; break;
case RRDP_HTTP_INI: case RRDP_HTTP_INI:
s = rrdp_get(id); s = rrdp_get(id);
@ -569,7 +561,7 @@ proc_rrdp(int fd)
switch (s->task) { switch (s->task) {
case NOTIFICATION: case NOTIFICATION:
rrdp_http_req(s->id, s->notifyuri, rrdp_http_req(s->id, s->notifyuri,
s->repository.last_mod); s->repository->last_mod);
break; break;
case SNAPSHOT: case SNAPSHOT:
case DELTA: case DELTA:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: rrdp_notification.c,v 1.17 2023/01/04 14:22:43 claudio Exp $ */ /* $OpenBSD: rrdp_notification.c,v 1.18 2023/06/23 11:36:24 claudio Exp $ */
/* /*
* Copyright (c) 2020 Nils Fisher <nils_fisher@hotmail.com> * Copyright (c) 2020 Nils Fisher <nils_fisher@hotmail.com>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@ -60,6 +60,7 @@ struct notification_xml {
char snapshot_hash[SHA256_DIGEST_LENGTH]; char snapshot_hash[SHA256_DIGEST_LENGTH];
struct delta_q delta_q; struct delta_q delta_q;
long long serial; long long serial;
long long min_serial;
int version; int version;
enum notification_scope scope; enum notification_scope scope;
}; };
@ -101,6 +102,21 @@ add_delta(struct notification_xml *nxml, const char *uri,
return 1; return 1;
} }
/* check that there are no holes in the list */
static int
check_delta(struct notification_xml *nxml)
{
struct delta_item *d;
long long serial = 0;
TAILQ_FOREACH(d, &nxml->delta_q, q) {
if (serial != 0 && serial + 1 != d->serial)
return 0;
serial = d->serial;
}
return 1;
}
static void static void
free_delta(struct delta_item *d) free_delta(struct delta_item *d)
{ {
@ -108,6 +124,36 @@ free_delta(struct delta_item *d)
free(d); free(d);
} }
/*
* Parse a delta serial and hash line at idx from the rrdp session state.
* Return the serial or 0 on error. If hash is non-NULL, it is set to the
* start of the hash string on success.
*/
static long long
delta_parse(struct rrdp_session *s, size_t idx, char **hash)
{
long long serial;
char *line, *ep;
if (hash != NULL)
*hash = NULL;
if (idx < 0 || idx >= sizeof(s->deltas) / sizeof(s->deltas[0]))
return 0;
if ((line = s->deltas[idx]) == NULL)
return 0;
errno = 0;
serial = strtoll(line, &ep, 10);
if (line[0] == '\0' || *ep != ' ')
return 0;
if (serial <= 0 || (errno == ERANGE && serial == LLONG_MAX))
return 0;
if (hash != NULL)
*hash = ep + 1;
return serial;
}
static void static void
start_notification_elem(struct notification_xml *nxml, const char **attr) start_notification_elem(struct notification_xml *nxml, const char **attr)
{ {
@ -149,6 +195,10 @@ start_notification_elem(struct notification_xml *nxml, const char **attr)
PARSE_FAIL(p, "parse failed - incomplete " PARSE_FAIL(p, "parse failed - incomplete "
"notification attributes"); "notification attributes");
/* Limit deltas to the ones which matter for us. */
if (nxml->min_serial == 0 && nxml->serial > MAX_RRDP_DELTAS)
nxml->min_serial = nxml->serial - MAX_RRDP_DELTAS;
nxml->scope = NOTIFICATION_SCOPE_NOTIFICATION; nxml->scope = NOTIFICATION_SCOPE_NOTIFICATION;
} }
@ -161,6 +211,9 @@ end_notification_elem(struct notification_xml *nxml)
PARSE_FAIL(p, "parse failed - exited notification " PARSE_FAIL(p, "parse failed - exited notification "
"elem unexpectedely"); "elem unexpectedely");
nxml->scope = NOTIFICATION_SCOPE_END; nxml->scope = NOTIFICATION_SCOPE_END;
if (!check_delta(nxml))
PARSE_FAIL(p, "parse failed - delta list has holes");
} }
static void static void
@ -247,11 +300,12 @@ start_delta_elem(struct notification_xml *nxml, const char **attr)
if (hasUri != 1 || hasHash != 1 || delta_serial == 0) if (hasUri != 1 || hasHash != 1 || delta_serial == 0)
PARSE_FAIL(p, "parse failed - incomplete delta attributes"); PARSE_FAIL(p, "parse failed - incomplete delta attributes");
/* Delta serial must be smaller or equal to the notification serial */
if (nxml->serial < delta_serial)
PARSE_FAIL(p, "parse failed - bad delta serial");
/* optimisation, add only deltas that could be interesting */ /* optimisation, add only deltas that could be interesting */
if (nxml->repository->serial != 0 && if (nxml->min_serial < delta_serial) {
nxml->repository->serial < delta_serial &&
nxml->repository->session_id != NULL &&
strcmp(nxml->session_id, nxml->repository->session_id) == 0) {
if (add_delta(nxml, delta_uri, delta_hash, delta_serial) == 0) if (add_delta(nxml, delta_uri, delta_hash, delta_serial) == 0)
PARSE_FAIL(p, "parse failed - adding delta failed"); PARSE_FAIL(p, "parse failed - adding delta failed");
} }
@ -333,6 +387,7 @@ new_notification_xml(XML_Parser p, struct rrdp_session *repository,
nxml->repository = repository; nxml->repository = repository;
nxml->current = current; nxml->current = current;
nxml->notifyuri = notifyuri; nxml->notifyuri = notifyuri;
nxml->min_serial = delta_parse(repository, 0, NULL);
XML_SetElementHandler(nxml->parser, notification_xml_elem_start, XML_SetElementHandler(nxml->parser, notification_xml_elem_start,
notification_xml_elem_end); notification_xml_elem_end);
@ -343,6 +398,16 @@ new_notification_xml(XML_Parser p, struct rrdp_session *repository,
return nxml; return nxml;
} }
static void
free_delta_queue(struct notification_xml *nxml)
{
while (!TAILQ_EMPTY(&nxml->delta_q)) {
struct delta_item *d = TAILQ_FIRST(&nxml->delta_q);
TAILQ_REMOVE(&nxml->delta_q, d, q);
free_delta(d);
}
}
void void
free_notification_xml(struct notification_xml *nxml) free_notification_xml(struct notification_xml *nxml)
{ {
@ -351,12 +416,86 @@ free_notification_xml(struct notification_xml *nxml)
free(nxml->session_id); free(nxml->session_id);
free(nxml->snapshot_uri); free(nxml->snapshot_uri);
while (!TAILQ_EMPTY(&nxml->delta_q)) { free_delta_queue(nxml);
struct delta_item *d = TAILQ_FIRST(&nxml->delta_q); free(nxml);
}
/*
* Collect a list of deltas to store in the repository state.
*/
static void
notification_collect_deltas(struct notification_xml *nxml)
{
struct delta_item *d;
long long keep_serial = 0;
size_t cur_idx = 0, max_deltas;
char *hash;
max_deltas =
sizeof(nxml->current->deltas) / sizeof(nxml->current->deltas[0]);
if (nxml->serial > (long long)max_deltas)
keep_serial = nxml->serial - max_deltas + 1;
TAILQ_FOREACH(d, &nxml->delta_q, q) {
if (d->serial >= keep_serial) {
assert(cur_idx < max_deltas);
hash = hex_encode(d->hash, sizeof(d->hash));
if (asprintf(&nxml->current->deltas[cur_idx++],
"%lld %s", d->serial, hash) == -1)
err(1, NULL);
free(hash);
}
}
}
/*
* Validate the delta list with the information from the repository state.
* Remove all obsolete deltas so that the list starts with the delta with
* serial nxml->repository->serial + 1.
* Returns 1 if all deltas were valid and 0 on failure.
*/
static int
notification_check_deltas(struct notification_xml *nxml)
{
struct delta_item *d, *nextd;
char *hash, *exp_hash;
long long exp_serial, new_serial;
size_t exp_idx = 0;
exp_serial = delta_parse(nxml->repository, exp_idx++, &exp_hash);
new_serial = nxml->repository->serial + 1;
/* compare hash of delta against repository state info */
TAILQ_FOREACH_SAFE(d, &nxml->delta_q, q, nextd) {
while (exp_serial != 0 && exp_serial < d->serial) {
exp_serial = delta_parse(nxml->repository,
exp_idx++, &exp_hash);
}
if (d->serial == exp_serial) {
hash = hex_encode(d->hash, sizeof(d->hash));
if (strcmp(hash, exp_hash) != 0) {
warnx("%s: %s#%lld unexpected delta "
"mutation (expected %s, got %s)",
nxml->notifyuri, nxml->session_id,
exp_serial, hash, exp_hash);
free(hash);
return 0;
}
free(hash);
exp_serial = delta_parse(nxml->repository,
exp_idx++, &exp_hash);
}
/* is this delta needed? */
if (d->serial < new_serial) {
TAILQ_REMOVE(&nxml->delta_q, d, q); TAILQ_REMOVE(&nxml->delta_q, d, q);
free_delta(d); free_delta(d);
} }
free(nxml); }
return 1;
} }
/* /*
@ -369,11 +508,9 @@ free_notification_xml(struct notification_xml *nxml)
enum rrdp_task enum rrdp_task
notification_done(struct notification_xml *nxml, char *last_mod) notification_done(struct notification_xml *nxml, char *last_mod)
{ {
struct delta_item *d;
long long s, last_s = 0;
nxml->current->last_mod = last_mod; nxml->current->last_mod = last_mod;
nxml->current->session_id = xstrdup(nxml->session_id); nxml->current->session_id = xstrdup(nxml->session_id);
notification_collect_deltas(nxml);
/* check the that the session_id was valid and still the same */ /* check the that the session_id was valid and still the same */
if (nxml->repository->session_id == NULL || if (nxml->repository->session_id == NULL ||
@ -384,6 +521,10 @@ notification_done(struct notification_xml *nxml, char *last_mod)
if (nxml->repository->serial == 0) if (nxml->repository->serial == 0)
goto snapshot; goto snapshot;
/* check that all needed deltas are available and valid */
if (!notification_check_deltas(nxml))
goto snapshot;
if (nxml->repository->serial > nxml->serial) if (nxml->repository->serial > nxml->serial)
warnx("%s: serial number decreased from %lld to %lld", warnx("%s: serial number decreased from %lld to %lld",
nxml->notifyuri, nxml->repository->serial, nxml->serial); nxml->notifyuri, nxml->repository->serial, nxml->serial);
@ -399,14 +540,12 @@ notification_done(struct notification_xml *nxml, char *last_mod)
if (nxml->serial - nxml->repository->serial > MAX_RRDP_DELTAS) if (nxml->serial - nxml->repository->serial > MAX_RRDP_DELTAS)
goto snapshot; goto snapshot;
/* check that all needed deltas are available */ /* no deltas queued */
s = nxml->repository->serial + 1; if (TAILQ_EMPTY(&nxml->delta_q))
TAILQ_FOREACH(d, &nxml->delta_q, q) {
if (d->serial != s++)
goto snapshot; goto snapshot;
last_s = d->serial;
} /* first possible delta is no match */
if (last_s != nxml->serial) if (nxml->repository->serial + 1 != TAILQ_FIRST(&nxml->delta_q)->serial)
goto snapshot; goto snapshot;
/* update via delta possible */ /* update via delta possible */
@ -416,6 +555,7 @@ notification_done(struct notification_xml *nxml, char *last_mod)
snapshot: snapshot:
/* update via snapshot download */ /* update via snapshot download */
free_delta_queue(nxml);
nxml->current->serial = nxml->serial; nxml->current->serial = nxml->serial;
return SNAPSHOT; return SNAPSHOT;
} }

View File

@ -1,4 +1,4 @@
/* $OpenBSD: x509.c,v 1.72 2023/06/20 11:06:47 job Exp $ */ /* $OpenBSD: x509.c,v 1.73 2023/06/23 15:32:15 tb Exp $ */
/* /*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org> * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@ -146,8 +146,14 @@ x509_get_aki(X509 *x, const char *fn, char **aki)
*aki = NULL; *aki = NULL;
akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &crit, NULL); akid = X509_get_ext_d2i(x, NID_authority_key_identifier, &crit, NULL);
if (akid == NULL) if (akid == NULL) {
if (crit != -1) {
warnx("%s: RFC 6487 section 4.8.3: error parsing AKI",
fn);
return 0;
}
return 1; return 1;
}
if (crit != 0) { if (crit != 0) {
warnx("%s: RFC 6487 section 4.8.3: " warnx("%s: RFC 6487 section 4.8.3: "
"AKI: extension not non-critical", fn); "AKI: extension not non-critical", fn);
@ -200,8 +206,14 @@ x509_get_ski(X509 *x, const char *fn, char **ski)
*ski = NULL; *ski = NULL;
os = X509_get_ext_d2i(x, NID_subject_key_identifier, &crit, NULL); os = X509_get_ext_d2i(x, NID_subject_key_identifier, &crit, NULL);
if (os == NULL) if (os == NULL) {
if (crit != -1) {
warnx("%s: RFC 6487 section 4.8.2: error parsing SKI",
fn);
return 0;
}
return 1; return 1;
}
if (crit != 0) { if (crit != 0) {
warnx("%s: RFC 6487 section 4.8.2: " warnx("%s: RFC 6487 section 4.8.2: "
"SKI: extension not non-critical", fn); "SKI: extension not non-critical", fn);
@ -258,6 +270,20 @@ x509_get_purpose(X509 *x, const char *fn)
if (X509_check_ca(x) == 1) { if (X509_check_ca(x) == 1) {
bc = X509_get_ext_d2i(x, NID_basic_constraints, &crit, NULL); bc = X509_get_ext_d2i(x, NID_basic_constraints, &crit, NULL);
if (bc == NULL) {
if (crit != -1)
warnx("%s: RFC 6487 section 4.8.1: "
"error parsing basic constraints", fn);
else
warnx("%s: RFC 6487 section 4.8.1: "
"missing basic constraints", fn);
goto out;
}
if (crit != 1) {
warnx("%s: RFC 6487 section 4.8.1: Basic Constraints "
"must be marked critical", fn);
goto out;
}
if (bc->pathlen != NULL) { if (bc->pathlen != NULL) {
warnx("%s: RFC 6487 section 4.8.1: Path Length " warnx("%s: RFC 6487 section 4.8.1: Path Length "
"Constraint must be absent", fn); "Constraint must be absent", fn);
@ -274,6 +300,9 @@ x509_get_purpose(X509 *x, const char *fn)
eku = X509_get_ext_d2i(x, NID_ext_key_usage, &crit, NULL); eku = X509_get_ext_d2i(x, NID_ext_key_usage, &crit, NULL);
if (eku == NULL) { if (eku == NULL) {
if (crit != -1)
warnx("%s: error parsing EKU", fn);
else
warnx("%s: EKU: extension missing", fn); warnx("%s: EKU: extension missing", fn);
goto out; goto out;
} }
@ -372,13 +401,13 @@ x509_get_aia(X509 *x, const char *fn, char **aia)
*aia = NULL; *aia = NULL;
info = X509_get_ext_d2i(x, NID_info_access, &crit, NULL); info = X509_get_ext_d2i(x, NID_info_access, &crit, NULL);
if (info == NULL) if (info == NULL) {
if (crit != -1) {
warnx("%s: RFC 6487 section 4.8.7: error parsing AIA",
fn);
return 0;
}
return 1; return 1;
if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0) {
warnx("%s: RFC 6487 section 4.8.7: AIA must be absent from "
"a self-signed certificate", fn);
goto out;
} }
if (crit != 0) { if (crit != 0) {
@ -387,6 +416,12 @@ x509_get_aia(X509 *x, const char *fn, char **aia)
goto out; goto out;
} }
if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0) {
warnx("%s: RFC 6487 section 4.8.7: AIA must be absent from "
"a self-signed certificate", fn);
goto out;
}
if (sk_ACCESS_DESCRIPTION_num(info) != 1) { if (sk_ACCESS_DESCRIPTION_num(info) != 1) {
warnx("%s: RFC 6487 section 4.8.7: AIA: " warnx("%s: RFC 6487 section 4.8.7: AIA: "
"want 1 element, have %d", fn, "want 1 element, have %d", fn,
@ -428,8 +463,13 @@ x509_get_sia(X509 *x, const char *fn, char **sia)
*sia = NULL; *sia = NULL;
info = X509_get_ext_d2i(x, NID_sinfo_access, &crit, NULL); info = X509_get_ext_d2i(x, NID_sinfo_access, &crit, NULL);
if (info == NULL) if (info == NULL) {
if (crit != -1) {
warnx("%s: error parsing SIA", fn);
return 0;
}
return 1; return 1;
}
if (crit != 0) { if (crit != 0) {
warnx("%s: RFC 6487 section 4.8.8: " warnx("%s: RFC 6487 section 4.8.8: "
@ -546,11 +586,14 @@ x509_inherits(X509 *x)
STACK_OF(IPAddressFamily) *addrblk = NULL; STACK_OF(IPAddressFamily) *addrblk = NULL;
ASIdentifiers *asidentifiers = NULL; ASIdentifiers *asidentifiers = NULL;
const IPAddressFamily *af; const IPAddressFamily *af;
int i, rc = 0; int crit, i, rc = 0;
addrblk = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); addrblk = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &crit, NULL);
if (addrblk == NULL) if (addrblk == NULL) {
if (crit != -1)
warnx("error parsing ipAddrBlock");
goto out; goto out;
}
/* /*
* Check by hand, since X509v3_addr_inherits() success only means that * Check by hand, since X509v3_addr_inherits() success only means that
@ -564,8 +607,11 @@ x509_inherits(X509 *x)
asidentifiers = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, NULL, asidentifiers = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, NULL,
NULL); NULL);
if (asidentifiers == NULL) if (asidentifiers == NULL) {
if (crit != -1)
warnx("error parsing asIdentifiers");
goto out; goto out;
}
/* We need to have AS numbers and don't want RDIs. */ /* We need to have AS numbers and don't want RDIs. */
if (asidentifiers->asnum == NULL || asidentifiers->rdi != NULL) if (asidentifiers->asnum == NULL || asidentifiers->rdi != NULL)
@ -590,14 +636,18 @@ x509_any_inherits(X509 *x)
{ {
STACK_OF(IPAddressFamily) *addrblk = NULL; STACK_OF(IPAddressFamily) *addrblk = NULL;
ASIdentifiers *asidentifiers = NULL; ASIdentifiers *asidentifiers = NULL;
int rc = 0; int crit, rc = 0;
addrblk = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); addrblk = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, &crit, NULL);
if (addrblk == NULL && crit != -1)
warnx("error parsing ipAddrBlock");
if (X509v3_addr_inherits(addrblk)) if (X509v3_addr_inherits(addrblk))
rc = 1; rc = 1;
asidentifiers = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, NULL, asidentifiers = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, &crit,
NULL); NULL);
if (asidentifiers == NULL && crit != -1)
warnx("error parsing asIdentifiers");
if (X509v3_asid_inherits(asidentifiers)) if (X509v3_asid_inherits(asidentifiers))
rc = 1; rc = 1;
@ -624,8 +674,14 @@ x509_get_crl(X509 *x, const char *fn, char **crl)
*crl = NULL; *crl = NULL;
crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &crit, NULL); crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, &crit, NULL);
if (crldp == NULL) if (crldp == NULL) {
if (crit != -1) {
warnx("%s: RFC 6487 section 4.8.6: failed to parse "
"CRL distribution points", fn);
return 0;
}
return 1; return 1;
}
if (crit != 0) { if (crit != 0) {
warnx("%s: RFC 6487 section 4.8.6: " warnx("%s: RFC 6487 section 4.8.6: "

View File

@ -1,4 +1,4 @@
/* $OpenBSD: smtp_session.c,v 1.434 2023/05/31 16:51:46 op Exp $ */ /* $OpenBSD: smtp_session.c,v 1.435 2023/06/23 18:32:28 op Exp $ */
/* /*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org> * Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@ -212,6 +212,7 @@ static int smtp_check_starttls(struct smtp_session *, const char *);
static int smtp_check_mail_from(struct smtp_session *, const char *); static int smtp_check_mail_from(struct smtp_session *, const char *);
static int smtp_check_rcpt_to(struct smtp_session *, const char *); static int smtp_check_rcpt_to(struct smtp_session *, const char *);
static int smtp_check_data(struct smtp_session *, const char *); static int smtp_check_data(struct smtp_session *, const char *);
static int smtp_check_noop(struct smtp_session *, const char *);
static int smtp_check_noparam(struct smtp_session *, const char *); static int smtp_check_noparam(struct smtp_session *, const char *);
static void smtp_filter_phase(enum filter_phase, struct smtp_session *, const char *); static void smtp_filter_phase(enum filter_phase, struct smtp_session *, const char *);
@ -276,7 +277,7 @@ static struct {
{ CMD_DATA, FILTER_DATA, "DATA", smtp_check_data, smtp_proceed_data }, { CMD_DATA, FILTER_DATA, "DATA", smtp_check_data, smtp_proceed_data },
{ CMD_RSET, FILTER_RSET, "RSET", smtp_check_rset, smtp_proceed_rset }, { CMD_RSET, FILTER_RSET, "RSET", smtp_check_rset, smtp_proceed_rset },
{ CMD_QUIT, FILTER_QUIT, "QUIT", smtp_check_noparam, smtp_proceed_quit }, { CMD_QUIT, FILTER_QUIT, "QUIT", smtp_check_noparam, smtp_proceed_quit },
{ CMD_NOOP, FILTER_NOOP, "NOOP", smtp_check_noparam, smtp_proceed_noop }, { CMD_NOOP, FILTER_NOOP, "NOOP", smtp_check_noop, smtp_proceed_noop },
{ CMD_HELP, FILTER_HELP, "HELP", smtp_check_noparam, smtp_proceed_help }, { CMD_HELP, FILTER_HELP, "HELP", smtp_check_noparam, smtp_proceed_help },
{ CMD_WIZ, FILTER_WIZ, "WIZ", smtp_check_noparam, smtp_proceed_wiz }, { CMD_WIZ, FILTER_WIZ, "WIZ", smtp_check_noparam, smtp_proceed_wiz },
{ CMD_COMMIT, FILTER_COMMIT, ".", smtp_check_noparam, smtp_proceed_commit }, { CMD_COMMIT, FILTER_COMMIT, ".", smtp_check_noparam, smtp_proceed_commit },
@ -1343,8 +1344,13 @@ smtp_command(struct smtp_session *s, char *line)
break; break;
case CMD_NOOP: case CMD_NOOP:
<<<<<<< smtp_session.c
if (!smtp_check_noparam(s, args)) if (!smtp_check_noparam(s, args))
break; break;
=======
if (!smtp_check_noop(s, args))
break;
>>>>>>> 1.435
smtp_filter_phase(FILTER_NOOP, s, NULL); smtp_filter_phase(FILTER_NOOP, s, NULL);
break; break;
@ -1630,6 +1636,12 @@ smtp_check_data(struct smtp_session *s, const char *args)
return 1; return 1;
} }
static int
smtp_check_noop(struct smtp_session *s, const char *args)
{
return 1;
}
static int static int
smtp_check_noparam(struct smtp_session *s, const char *args) smtp_check_noparam(struct smtp_session *s, const char *args)
{ {