Re: use rtalloc_mpath in pf_route{,6}

2021-02-15 Thread Claudio Jeker
On Mon, Feb 15, 2021 at 08:02:37PM +1000, David Gwynne wrote:
> if you have multiple links to the same destination, this will let you
> use them via route-to/reply-to/dup-to.
> 
> ok?
> 
> Index: pf.c
> ===
> RCS file: /cvs/src/sys/net/pf.c,v
> retrieving revision 1.1110
> diff -u -p -r1.1110 pf.c
> --- pf.c  12 Feb 2021 16:16:10 -  1.1110
> +++ pf.c  15 Feb 2021 09:59:50 -
> @@ -6020,7 +6020,7 @@ pf_route(struct pf_pdesc *pd, struct pf_
>   dst->sin_addr = s->rt_addr.v4;
>   rtableid = m0->m_pkthdr.ph_rtableid;
>  
> - rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid);
> + rt = rtalloc_mpath(sintosa(dst), >ip_src.s_addr, rtableid);
>   if (!rtisvalid(rt)) {
>   if (s->rt != PF_DUPTO) {
>   pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_HOST,
> @@ -6162,7 +6162,8 @@ pf_route6(struct pf_pdesc *pd, struct pf
>   dst->sin6_addr = s->rt_addr.v6;
>   rtableid = m0->m_pkthdr.ph_rtableid;
>  
> - rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid);
> + rt = rtalloc_mpath(sin6tosa(dst), >ip6_src.s6_addr32[0],
> + rtableid);
>   if (!rtisvalid(rt)) {
>   if (s->rt != PF_DUPTO) {
>   pf_send_icmp(m0, ICMP6_DST_UNREACH,
> 

OK claudio@

-- 
:wq Claudio



Re: rpki-client: get Authority Information Access (AIA) from CA & EE certs

2021-02-15 Thread Claudio Jeker
On Sun, Feb 14, 2021 at 05:41:55PM +, Job Snijders wrote:
> Make the AIA more easily available for debugging purposes & future
> changesets
> 
> In the context of the RPKI, the AIA extension identifies the publication
> point of the certificate of the issuer of the certificate in which the
> extension appears. A single reference to the publication point of the
> immediate superior certificate MUST be present, except for a
> "self-signed" certificate.
> 
> OK?

I'm not against this going in but I think there is some improvements that
should be made. Some of it inline.

The extra data stored increases the memory usage by 16MB or 3.5% which is ok.
Also the data is already kind of known via the AKI / SKI stack but for
individual files it is much easier to to walk backup up the tree via AIA.

> Index: regress/usr.sbin/rpki-client/test-cert.c
> ===
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-cert.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 test-cert.c
> --- regress/usr.sbin/rpki-client/test-cert.c  8 Feb 2021 09:28:58 -   
> 1.8
> +++ regress/usr.sbin/rpki-client/test-cert.c  14 Feb 2021 17:29:17 -
> @@ -52,6 +52,8 @@ cert_print(const struct cert *p)
>   printf("Subject key identifier: %s\n", p->ski);
>   if (p->aki != NULL)
>   printf("Authority key identifier: %s\n", p->aki);
> + if (p->aia != NULL)
> + printf("Authority info access: %s\n", p->aia);
>  
>   for (i = 0; i < p->asz; i++)
>   switch (p->as[i].type) {
> Index: regress/usr.sbin/rpki-client/test-gbr.c
> ===
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-gbr.c,v
> retrieving revision 1.1
> diff -u -p -r1.1 test-gbr.c
> --- regress/usr.sbin/rpki-client/test-gbr.c   9 Dec 2020 11:30:44 -   
> 1.1
> +++ regress/usr.sbin/rpki-client/test-gbr.c   14 Feb 2021 17:29:17 -
> @@ -42,6 +42,7 @@ gbr_print(const struct gbr *p)
>  
>   printf("Subject key identifier: %s\n", p->ski);
>   printf("Authority key identifier: %s\n", p->aki);
> + printf("Authority info access: %s\n", p->aia);
>   printf("vcard:\n%s", p->vcard);
>  }
>  
> Index: regress/usr.sbin/rpki-client/test-mft.c
> ===
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-mft.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 test-mft.c
> --- regress/usr.sbin/rpki-client/test-mft.c   9 Nov 2020 16:13:02 -   
> 1.10
> +++ regress/usr.sbin/rpki-client/test-mft.c   14 Feb 2021 17:29:17 -
> @@ -54,6 +54,7 @@ mft_print(const struct mft *p)
>  
>   printf("Subject key identifier: %s\n", p->ski);
>   printf("Authority key identifier: %s\n", p->aki);
> + printf("Authority info access: %s\n", p->aia);
>   for (i = 0; i < p->filesz; i++) {
>   b64_ntop(p->files[i].hash, sizeof(p->files[i].hash),
>   hash, sizeof(hash));
> Index: regress/usr.sbin/rpki-client/test-roa.c
> ===
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/test-roa.c,v
> retrieving revision 1.8
> diff -u -p -r1.8 test-roa.c
> --- regress/usr.sbin/rpki-client/test-roa.c   29 Jan 2021 10:15:42 -  
> 1.8
> +++ regress/usr.sbin/rpki-client/test-roa.c   14 Feb 2021 17:29:17 -
> @@ -42,6 +42,7 @@ roa_print(const struct roa *p)
>  
>   printf("Subject key identifier: %s\n", p->ski);
>   printf("Authority key identifier: %s\n", p->aki);
> + printf("Authority info access: %s\n", p->aia);
>   printf("asID: %" PRIu32 "\n", p->asid);
>   for (i = 0; i < p->ipsz; i++) {
>   ip_addr_print(>ips[i].addr,
> Index: regress/usr.sbin/rpki-client/Makefile.inc
> ===
> RCS file: /cvs/src/regress/usr.sbin/rpki-client/Makefile.inc,v
> retrieving revision 1.6
> diff -u -p -r1.6 Makefile.inc
> --- regress/usr.sbin/rpki-client/Makefile.inc 3 Feb 2021 10:45:12 -   
> 1.6
> +++ regress/usr.sbin/rpki-client/Makefile.inc 14 Feb 2021 17:29:17 -
> @@ -4,9 +4,9 @@
>  
>  PROGS += test-ip
>  PROGS += test-cert
> +PROGS += test-gbr
>  PROGS += test-mft
>  PROGS += test-roa
> -PROGS += test-gbr
>  PROGS += test-tal
>  
>  .for p in ${PROGS}

Regress tests are OK.

> Index: usr.sbin/rpki-client/cert.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 cert.c
> --- usr.sbin/rpki-client/cert.c   8 Feb 2021 09:22:53 -   1.25
> +++ usr.sbin/rpki-client/cert.c   14 Feb 2021 17:29:18 -
> @@ -1079,6 +1079,11 @@ cert_parse_inner(X509 **xp, const char *
>   case NID_crl_distribution_points:
>   /* ignored here, handled later */
>   break;
> + case 

Re: change rpki-client repository code

2021-02-15 Thread Claudio Jeker
On Mon, Feb 15, 2021 at 04:53:17PM +0100, Theo Buehler wrote:
> On Fri, Feb 12, 2021 at 10:01:38AM +0100, Claudio Jeker wrote:
> > On Mon, Feb 08, 2021 at 05:15:40PM +0100, Claudio Jeker wrote:
> > > Split the repository code into two parts:
> > > 
> > > - fetch of the trust anchors (the certs referenced by TAL files)
> > > - fetch of the MFT files of a repository
> > > 
> > > While the two things kind of look similar there are some differences.
> > > 
> > > - TA files are loaded via rsync or https URI (only one file needs to be
> > >   loaded)
> > > - MFT files need everything inside the repository to be loaded since they
> > >   reference to other files (.roa, .cer, .crl). These repositories are
> > >   synced once with rsync and many mft may be part of a repo. Also these
> > >   repositories can be synced via rsync or RRDP
> > > 
> > > To simplify these diverse options it is time to split the code up.
> > > Introduce a ta_lookup() along with repo_lookup(). Refactor the repo_lookup
> > > code into subfunctions repo_alloc() and repo_fetch() (both are also used
> > > by ta_lookup()). Use the caRepository URI to figure out the base URI.
> > > Simplify rsync_uri_parse() into rsync_base_uri() which clips of excess
> > > directories from the URI (else thousends of individual rsync calls would
> > > be made against the RIR's CA repos).
> > > 
> > > The big change is that the layout of the cache directory is changed.
> > > The cache will now have two base directories:
> > > - ta/ (for all trust anchors)
> > > - rsync/ (for all other repositories)
> > > 
> > 
> > My plan at the moment is that rpki-client will split the cache directory
> > into three parts. ta/, rsync/, and rrdp/. This is done to ensure that data
> > does not get mixed up. Once this is in then my next step is to support
> > https:// links in TAL files and fetch the trust anchor via https instead
> > of rsync. Later RRDP will follow.
> 
> This looks good to me although I have a couple of small nits inline.
> 
> ok tb
> 
> > 
> > -- 
> > :wq Claudio
> > 
> > Index: extern.h
> > ===
> > RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> > retrieving revision 1.42
> > diff -u -p -r1.42 extern.h
> > --- extern.h8 Feb 2021 09:22:53 -   1.42
> > +++ extern.h8 Feb 2021 13:44:22 -
> > @@ -392,9 +392,7 @@ void proc_parser(int) __attribute__((n
> >  
> >  /* Rsync-specific. */
> >  
> > -int rsync_uri_parse(const char **, size_t *,
> > -   const char **, size_t *, const char **, size_t *,
> > -   enum rtype *, const char *);
> > +char   *rsync_base_uri(const char *);
> >  voidproc_rsync(char *, char *, int) 
> > __attribute__((noreturn));
> >  
> >  /* Logging (though really used for OpenSSL errors). */
> > Index: main.c
> > ===
> > RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
> > retrieving revision 1.98
> > diff -u -p -r1.98 main.c
> > --- main.c  5 Feb 2021 12:26:52 -   1.98
> > +++ main.c  8 Feb 2021 13:50:20 -
> > @@ -78,11 +78,12 @@
> >   * An rsync repository.
> >   */
> >  struct repo {
> > -   char*repo;  /* repository rsync URI */
> > -   char*local; /* local path name */
> > -   char*notify; /* RRDB notify URI if available */
> > -   size_t   id; /* identifier (array index) */
> > -   int  loaded; /* whether loaded or not */
> > +   char*repouri;   /* CA repository base URI */
> > +   char*local; /* local path name */
> > +   char*uris[2];   /* URIs to fetch from */
> > +   size_t   id;/* identifier (array index) */
> > +   int  uriidx;/* which URI is fetched */
> > +   int  loaded;/* whether loaded or not */
> >  };
> >  
> >  size_t entity_queue;
> > @@ -284,33 +285,12 @@ entityq_add(struct entityq *q, char *fil
> >  }
> >  
> >  /*
> > - * Look up a repository, queueing it for discovery if not found.
> > + * Allocat a new repository be extending the repotable.
> >   */
> > -static const struct repo *
> > -repo_lookup(const char *uri)
> > +static struct repo *
> > +

Re: RTR support for bgpd

2021-02-15 Thread Claudio Jeker
On Wed, Feb 10, 2021 at 05:30:02PM +0100, Claudio Jeker wrote:
> On Tue, Jan 26, 2021 at 10:31:40AM +0100, Claudio Jeker wrote:
> > This diff adds initial RTR (RPKI to Router) support to bgpd.
> > Instead of loading the roa-set table via the configuration bgpd will use
> > RTR to load the RPKI table from one or multiple RTR servers.
> > This has the benefit that in large setups only a few systems need to run
> > rpki-client instead of running it on every router.
> > 
> > Currently only RTR via TCP is supported. Basic 'bgpctl show rtr' output is
> > available to monitor sessions and 'bgpctl show sets' also shows the right
> > info. There is a lot more that can be added here but this diff is already
> > big enough.
> > 
> > Enjoy
> 
> I know this is a large diff but I would like to have somebody review it
> before commit. This will affect any kind of RPKI usage via roa-set or rtr
> session.
> 

Updated version after some input from job@. This now allows to run more
then one rtr session against the same IP address. Before the result was
weird.

-- 
:wq Claudio

Index: bgpctl/bgpctl.8
===
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.8,v
retrieving revision 1.95
diff -u -p -r1.95 bgpctl.8
--- bgpctl/bgpctl.8 10 May 2020 13:38:46 -  1.95
+++ bgpctl/bgpctl.8 26 Jan 2021 08:42:39 -
@@ -33,7 +33,7 @@ program controls the
 .Xr bgpd 8
 daemon.
 Commands may be abbreviated to the minimum unambiguous prefix; for example,
-.Cm s s
+.Cm s su
 for
 .Cm show summary .
 .Pp
@@ -409,6 +409,18 @@ or
 Multiple options can be used at the same time and the
 .Ar neighbor
 filter can be combined with other filters.
+.It Cm show rtr
+Show a list of all
+.Em RTR
+sessions, including information about the session state.
+.It Cm show sets
+Show a list summarizing all
+.Em roa-set ,
+.Em as-set ,
+.Em prefix-set ,
+and
+.Em origin-set
+tables.
 .It Cm show summary
 Show a list of all neighbors, including information about the session state
 and message counters:
Index: bgpctl/bgpctl.c
===
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.264
diff -u -p -r1.264 bgpctl.c
--- bgpctl/bgpctl.c 30 Dec 2020 07:31:19 -  1.264
+++ bgpctl/bgpctl.c 25 Jan 2021 18:06:13 -
@@ -216,6 +216,9 @@ main(int argc, char *argv[])
case SHOW_SET:
imsg_compose(ibuf, IMSG_CTL_SHOW_SET, 0, 0, -1, NULL, 0);
break;
+   case SHOW_RTR:
+   imsg_compose(ibuf, IMSG_CTL_SHOW_RTR, 0, 0, -1, NULL, 0);
+   break;
case SHOW_NEIGHBOR:
case SHOW_NEIGHBOR_TIMERS:
case SHOW_NEIGHBOR_TERSE:
@@ -393,18 +396,19 @@ int
 show(struct imsg *imsg, struct parse_result *res)
 {
struct peer *p;
-   struct ctl_timer*t;
+   struct ctl_timer t;
struct ctl_show_interface   *iface;
struct ctl_show_nexthop *nh;
-   struct ctl_show_set *set;
+   struct ctl_show_set  set;
+   struct ctl_show_rtr  rtr;
struct kroute_full  *kf;
struct ktable   *kt;
struct ctl_show_rib  rib;
+   struct rde_memstats  stats;
+   struct rde_hashstats hash;
u_char  *asdata;
-   struct rde_memstats stats;
-   struct rde_hashstatshash;
-   u_int   rescode, ilen;
-   size_t  aslen;
+   u_intrescode, ilen;
+   size_t   aslen;
 
switch (imsg->hdr.type) {
case IMSG_CTL_SHOW_NEIGHBOR:
@@ -412,9 +416,11 @@ show(struct imsg *imsg, struct parse_res
output->neighbor(p, res);
break;
case IMSG_CTL_SHOW_TIMER:
-   t = imsg->data;
-   if (t->type > 0 && t->type < Timer_Max)
-   output->timer(t);
+   if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(t))
+   errx(1, "wrong imsg len");
+   memcpy(, imsg->data, sizeof(t));
+   if (t.type > 0 && t.type < Timer_Max)
+   output->timer();
break;
case IMSG_CTL_SHOW_INTERFACE:
iface = imsg->data;
@@ -463,16 +469,28 @@ show(struct imsg *imsg, struct parse_res
output->attr(imsg->data, ilen, res);
break;
case IMSG_CTL_SHOW_RIB_MEM:
+   if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(stats))
+   errx(1, "wrong imsg len");
memcpy(, imsg->data, sizeof(stats));
output->rib_mem();
break;
case IMSG_CTL_SHOW_RIB_HASH:
+  

Re: rpki-client: get Authority Information Access (AIA) from CA & EE certs

2021-02-15 Thread Claudio Jeker
On Mon, Feb 15, 2021 at 04:58:50PM +, Job Snijders wrote:
> Hi,
> 
> Thank you for the review
> 
> On Mon, Feb 15, 2021 at 01:42:57PM +0100, Claudio Jeker wrote:
> > Please do not define variables in the middle of functions. 
> 
> now fixed
> 
> > > + AUTHORITY_INFO_ACCESS_free(info);
> > > +
> > > + return aia;
> > > +}
> > 
> > I really don't like the way x509_get_aia() is different to
> > x509_get_ski_ext and x509_get_aki_ext. The way the x509 extensions are
> > handled in rpki-client is strange. In x509_get_exts() the code walks over
> > all extensions and looks for the NID we're interested in.
> 
> Yes, they are different in style. I think x509_get_{ski,aki}_ext() might
> be 'the odd ones out': http://man.openbsd.org/X509_EXTENSION_get_data states:
> 
> "Most applications will want to parse or encode and add an
> extension: they should use the extension encode and decode functions
> instead such as X509_add1_ext_i2d(3) and X509_get_ext_d2i(3)."
> 
> Which is why I wrote x509_get_aia() to use X509_get_ext_d2i(3).

I did not imply that your code is wrong. I tend to agree that
x509_get_{ski,aki}_ext() need the rewrite.
 
> > x509_get_aia() makes this approach even more strange by actually not using
> > the ext but instead do a lookup from the x509 object directly. So why call
> > it in the for loop at all. Just do it directly.
> > 
> > Also the way the code is written in x509_get_exts() implies that x509
> > allows the same extension to be added more then once. Is that really true?
> > Wouldn't that be an error regarding RFC6487.
> 
> https://tools.ietf.org/html/rfc5280#section-4.2.2.1 reads:
> "An authorityInfoAccess extension may include multiple instances of
> the id-ad-caIssuers accessMethod."

But does it mention that only one authorityInfoAccess extension may be
included?
 
> Then https://tools.ietf.org/html/rfc6487#section-4.8.7 narrows it down:
> "In this profile, a single reference to the publication point of the
> immediate superior certificate MUST be present"
> 
> which is why i put "if (sk_ACCESS_DESCRIPTION_num(info) != 1) {" in
> x509_get_aia().

This part I have seen but my question was more aiming at the for() loop in 
x509_get_exts() where we loop over the array but actually x509_get_aia()
will always fetch the same data for each call
 
> > Anyway I would prefer if x509_get_ski_ext(), x509_get_aki_ext() and
> > x509_get_aia() all work the same way.
> 
> Perhaps x509_get_ski_ext() and x509_get_aki_ext() can be modified to use
> X509_get_ext_d2i(3) too.

They should and x509_get_exts() and the code in cert.c should be adjusted
as well. Let's see if I find the x509 hazmat suit.
 
> > You forgot to add *aia to at the start where *ski = *aki = NULL;
> 
> fixed.
> 
> > With the style and initialisation issue fixed I think this can go in
> > but as mentioned more x509 cleanup needs to follow.
> 
> OK?

There are memory leaks (none of the aia strings are freed) and also the io
read and write bits are missing. If you sure the AIA is only used in the
parser process then you can skip the io bits.
 
> Index: usr.sbin/rpki-client/cert.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.25
> diff -u -p -r1.25 cert.c
> --- usr.sbin/rpki-client/cert.c   8 Feb 2021 09:22:53 -   1.25
> +++ usr.sbin/rpki-client/cert.c   15 Feb 2021 16:54:05 -
> @@ -1079,6 +1079,11 @@ cert_parse_inner(X509 **xp, const char *
>   case NID_crl_distribution_points:
>   /* ignored here, handled later */
>   break;
> + case NID_info_access:
> + free(p.res->aia);
> + p.res->aia = x509_get_aia(x, p.fn);
> + c = (p.res->aia != NULL);
> + break;
>   case NID_authority_key_identifier:
>   free(p.res->aki);
>   p.res->aki = x509_get_aki_ext(ext, p.fn);
> Index: usr.sbin/rpki-client/gbr.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/gbr.c,v
> retrieving revision 1.4
> diff -u -p -r1.4 gbr.c
> --- usr.sbin/rpki-client/gbr.c4 Feb 2021 08:58:19 -   1.4
> +++ usr.sbin/rpki-client/gbr.c15 Feb 2021 16:54:05 -
> @@ -62,7 +62,7 @@ gbr_parse(X509 **x509, const char *fn)
>   err(1, NULL);
>   if ((p.res->vcard = strndup(cms, cmsz)) == NULL)
>   err(1, NULL);
> - if (!x509_get_ski_aki(*x509

Re: rpki-client: recallocarray conversions

2021-02-19 Thread Claudio Jeker
On Fri, Feb 19, 2021 at 10:27:06AM +0100, Theo Buehler wrote:
> As discussed a few days ago, there are a few reallocarray + memset that
> can be directly handled by recallocarray.

Fine with me.
 
> Index: main.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
> retrieving revision 1.101
> diff -u -p -r1.101 main.c
> --- main.c18 Feb 2021 10:10:20 -  1.101
> +++ main.c19 Feb 2021 08:56:19 -
> @@ -265,12 +265,12 @@ repo_alloc(void)
>  {
>   struct repo *rp;
>  
> - rt.repos = reallocarray(rt.repos, rt.reposz + 1, sizeof(struct repo));
> + rt.repos = recallocarray(rt.repos, rt.reposz, rt.reposz + 1,
> + sizeof(struct repo));
>   if (rt.repos == NULL)
> - err(1, "reallocarray");
> + err(1, "recallocarray");
>  
>   rp = [rt.reposz++];
> - memset(rp, 0, sizeof(struct repo));
>   rp->id = rt.reposz - 1;
>  
>   return rp;
> Index: mft.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
> retrieving revision 1.26
> diff -u -p -r1.26 mft.c
> --- mft.c 16 Feb 2021 07:58:30 -  1.26
> +++ mft.c 19 Feb 2021 07:04:25 -
> @@ -193,13 +193,12 @@ mft_parse_filehash(struct parse *p, cons
>  
>   /* Insert the filename and hash value. */
>  
> - p->res->files = reallocarray(p->res->files, p->res->filesz + 1,
> - sizeof(struct mftfile));
> + p->res->files = recallocarray(p->res->files, p->res->filesz,
> + p->res->filesz + 1, sizeof(struct mftfile));
>   if (p->res->files == NULL)
>   err(1, NULL);
>  
>   fent = >res->files[p->res->filesz++];
> - memset(fent, 0, sizeof(struct mftfile));
>  
>   fent->file = fn;
>   fn = NULL;
> Index: roa.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 roa.c
> --- roa.c 16 Feb 2021 07:58:30 -  1.14
> +++ roa.c 19 Feb 2021 07:07:30 -
> @@ -111,12 +111,11 @@ roa_parse_addr(const ASN1_OCTET_STRING *
>   /* FIXME: maximum check. */
>   }
>  
> - p->res->ips = reallocarray(p->res->ips,
> - p->res->ipsz + 1, sizeof(struct roa_ip));
> + p->res->ips = recallocarray(p->res->ips, p->res->ipsz, p->res->ipsz + 1,
> + sizeof(struct roa_ip));
>   if (p->res->ips == NULL)
>   err(1, NULL);
>   res = >res->ips[p->res->ipsz++];
> - memset(res, 0, sizeof(struct roa_ip));
>  
>   res->addr = addr;
>   res->afi = afi;
> 

-- 
:wq Claudio



rpki-client extra paranoia

2021-02-19 Thread Claudio Jeker
Better to make sure that all URI we ingest are sensitive. Similar check
is already done in cert.c so also do it for the TAL files (even though
these are normally controled by the user).

OK?
-- 
:wq Claudio

Index: tal.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/tal.c,v
retrieving revision 1.26
diff -u -p -r1.26 tal.c
--- tal.c   8 Jan 2021 08:09:07 -   1.26
+++ tal.c   19 Feb 2021 09:21:18 -
@@ -82,6 +82,7 @@ tal_parse_buffer(const char *fn, char *b
char*nl, *line, *f, *file = NULL;
unsigned char   *der;
size_t   sz, dersz;
+   ssize_t  i;
int  rc = 0;
struct tal  *tal = NULL;
EVP_PKEY*pkey = NULL;
@@ -101,6 +102,13 @@ tal_parse_buffer(const char *fn, char *b
if (*line == '\0')
break;
 
+   /* make sure only US-ASCII chars are in the URL */
+   for (i = 0; i < nl - line; i++) {
+   if (isalnum(line[i]) || ispunct(line[i]))
+   continue;
+   warnx("%s: invalid URI", fn);
+   goto out;
+   }
/* Check that the URI is sensible */
if (!(strncasecmp(line, "https://;, 8) == 0 ||
strncasecmp(line, "rsync://", 8) == 0)) {



Teach rpki-client some https

2021-02-19 Thread Claudio Jeker
Some TAL files now include an https URI where the TA can be fetched from.
With this diff rpki-client will download the TA from https unless that
fails and then fall back to rsync.

This is not yet perfect but the diff is already large enough (adding a
full event based https client based on ftp codebase). For RRDP more a lot
more is required and I probably will refactor the main.c code then.

At the moment this adds a local mkostempat() function to implement
mkostemp() but with openat() instead of open(). I hope in the future libc
will provide something.

Thanks in advance for all the feedback
-- 
:wq Claudio

Index: Makefile
===
RCS file: /cvs/src/usr.sbin/rpki-client/Makefile,v
retrieving revision 1.18
diff -u -p -r1.18 Makefile
--- Makefile4 Feb 2021 08:10:24 -   1.18
+++ Makefile19 Feb 2021 14:21:08 -
@@ -1,13 +1,14 @@
 #  $OpenBSD: Makefile,v 1.18 2021/02/04 08:10:24 claudio Exp $
 
 PROG=  rpki-client
-SRCS=  as.c cert.c cms.c crl.c gbr.c io.c ip.c log.c main.c mft.c mkdir.c \
-   output.c output-bgpd.c output-bird.c output-csv.c output-json.c \
-   parser.c roa.c rsync.c tal.c validate.c x509.c
+SRCS=  as.c cert.c cms.c crl.c gbr.c http.c io.c ip.c log.c main.c mft.c \
+   mkdir.c mkostempat.c output.c output-bgpd.c output-bird.c \
+   output-csv.c output-json.c parser.c roa.c rsync.c tal.c validate.c \
+   x509.c
 MAN=   rpki-client.8
 
-LDADD+= -lcrypto -lutil
-DPADD+= ${LIBCRYPTO} ${LIBUTIL}
+LDADD+= -ltls -lssl -lcrypto -lutil
+DPADD+= ${LIBTLS} ${LIBSSL} ${LIBCRYPTO} ${LIBUTIL}
 
 CFLAGS+= -Wall -I${.CURDIR}
 CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.46
diff -u -p -r1.46 extern.h
--- extern.h19 Feb 2021 08:14:49 -  1.46
+++ extern.h19 Feb 2021 14:20:27 -
@@ -399,6 +399,10 @@ voidproc_parser(int) __attribute__((n
 char   *rsync_base_uri(const char *);
 voidproc_rsync(char *, char *, int) __attribute__((noreturn));
 
+/* Http-specific. */
+
+voidproc_http(char *, int);
+
 /* Logging (though really used for OpenSSL errors). */
 
 voidcryptowarnx(const char *, ...)
@@ -417,6 +421,7 @@ void io_str_buffer(struct ibuf *, cons
 voidio_simple_read(int, void *, size_t);
 voidio_buf_read_alloc(int, void **, size_t *);
 voidio_str_read(int, char **);
+int io_recvfd(int, void *, size_t);
 
 /* X509 helpers. */
 
@@ -449,7 +454,8 @@ int  output_json(FILE *, struct vrp_tre
 void   logx(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
 
-intmkpath(int, const char *);
+intmkpathat(int, const char *);
+intmkostempat(int, char *, int);
 
 #defineRPKI_PATH_OUT_DIR   "/var/db/rpki-client"
 #defineRPKI_PATH_BASE_DIR  "/var/cache/rpki-client"
Index: http.c
===
RCS file: http.c
diff -N http.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ http.c  19 Feb 2021 17:32:26 -
@@ -0,0 +1,1223 @@
+/*
+ * Copyright (c) 2020 Nils Fisher 
+ * Copyright (c) 2020 Claudio Jeker 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*  $OpenBSD: fetch.c,v 1.197 2020/07/04 11:23:35 kn Exp $  */
+/*  $NetBSD: fetch.c,v 1.14 1997/08/18 10:20:20 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason Thorpe and Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in the
+ *documentation and/or other materials 

Re: change rpki-client repository code

2021-02-12 Thread Claudio Jeker
On Mon, Feb 08, 2021 at 05:15:40PM +0100, Claudio Jeker wrote:
> Split the repository code into two parts:
> 
> - fetch of the trust anchors (the certs referenced by TAL files)
> - fetch of the MFT files of a repository
> 
> While the two things kind of look similar there are some differences.
> 
> - TA files are loaded via rsync or https URI (only one file needs to be
>   loaded)
> - MFT files need everything inside the repository to be loaded since they
>   reference to other files (.roa, .cer, .crl). These repositories are
>   synced once with rsync and many mft may be part of a repo. Also these
>   repositories can be synced via rsync or RRDP
> 
> To simplify these diverse options it is time to split the code up.
> Introduce a ta_lookup() along with repo_lookup(). Refactor the repo_lookup
> code into subfunctions repo_alloc() and repo_fetch() (both are also used
> by ta_lookup()). Use the caRepository URI to figure out the base URI.
> Simplify rsync_uri_parse() into rsync_base_uri() which clips of excess
> directories from the URI (else thousends of individual rsync calls would
> be made against the RIR's CA repos).
> 
> The big change is that the layout of the cache directory is changed.
> The cache will now have two base directories:
> - ta/ (for all trust anchors)
> - rsync/ (for all other repositories)
> 

My plan at the moment is that rpki-client will split the cache directory
into three parts. ta/, rsync/, and rrdp/. This is done to ensure that data
does not get mixed up. Once this is in then my next step is to support
https:// links in TAL files and fetch the trust anchor via https instead
of rsync. Later RRDP will follow.

-- 
:wq Claudio

Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.42
diff -u -p -r1.42 extern.h
--- extern.h8 Feb 2021 09:22:53 -   1.42
+++ extern.h8 Feb 2021 13:44:22 -
@@ -392,9 +392,7 @@ void proc_parser(int) __attribute__((n
 
 /* Rsync-specific. */
 
-int rsync_uri_parse(const char **, size_t *,
-   const char **, size_t *, const char **, size_t *,
-   enum rtype *, const char *);
+char   *rsync_base_uri(const char *);
 voidproc_rsync(char *, char *, int) __attribute__((noreturn));
 
 /* Logging (though really used for OpenSSL errors). */
Index: main.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.98
diff -u -p -r1.98 main.c
--- main.c  5 Feb 2021 12:26:52 -   1.98
+++ main.c  8 Feb 2021 13:50:20 -
@@ -78,11 +78,12 @@
  * An rsync repository.
  */
 struct repo {
-   char*repo;  /* repository rsync URI */
-   char*local; /* local path name */
-   char*notify; /* RRDB notify URI if available */
-   size_t   id; /* identifier (array index) */
-   int  loaded; /* whether loaded or not */
+   char*repouri;   /* CA repository base URI */
+   char*local; /* local path name */
+   char*uris[2];   /* URIs to fetch from */
+   size_t   id;/* identifier (array index) */
+   int  uriidx;/* which URI is fetched */
+   int  loaded;/* whether loaded or not */
 };
 
 size_t entity_queue;
@@ -284,33 +285,12 @@ entityq_add(struct entityq *q, char *fil
 }
 
 /*
- * Look up a repository, queueing it for discovery if not found.
+ * Allocat a new repository be extending the repotable.
  */
-static const struct repo *
-repo_lookup(const char *uri)
+static struct repo *
+repo_alloc(void)
 {
-   const char  *host, *mod;
-   size_t   hostsz, modsz, i;
-   char*local;
-   struct repo *rp;
-   struct ibuf *b;
-
-   if (!rsync_uri_parse(, ,
-   , , NULL, NULL, NULL, uri))
-   errx(1, "%s: malformed", uri);
-
-   if (asprintf(, "%.*s/%.*s", (int)hostsz, host,
-   (int)modsz, mod) == -1)
-   err(1, "asprintf");
-
-   /* Look up in repository table. */
-
-   for (i = 0; i < rt.reposz; i++) {
-   if (strcmp(rt.repos[i].local, local))
-   continue;
-   free(local);
-   return [i];
-   }
+   struct repo *rp;
 
rt.repos = reallocarray(rt.repos,
rt.reposz + 1, sizeof(struct repo));
@@ -320,28 +300,99 @@ repo_lookup(const char *uri)
rp = [rt.reposz++];
memset(rp, 0, sizeof(struct repo));
rp->id = rt.reposz - 1;
-   rp->local = local;
 
-   if ((rp->repo = strndup(uri, mod + modsz - uri)) == NULL)
-

Re: route(1): add an address family validation

2021-08-27 Thread Claudio Jeker
On Fri, Aug 27, 2021 at 03:58:23PM +0900, morimoto wrote:
> hi,
> I found an interesting issue while toying routing.
> route(1) accepts IPv4 destination and IPv6 gateway entry.
> command is as below:
> route add 192.0.2.1 2001:db8::1
> 
> Curiously it has no error.
> The entry is pointless, I think it should teach a mistake.
> If destination and gateway address family are not the same, it should return 
> error.
> 
> Comments?

I don't think the entry is pointless. There are setups where nexthop of
different address family do make sense. Things like rfc5549 can do
IPv4 over IPv6 Core. In some cases this is used for network autodiscovery
(using IPv6 link-local addresses as nexthops). 
Because of this I think it would make more sense to make this actually
work.
 
> Index: sbin/route/route.c
> ===
> RCS file: /cvs/src/sbin/route/route.c,v
> retrieving revision 1.254
> diff -u -p -r1.254 route.c
> --- sbin/route/route.c12 Mar 2021 19:35:43 -  1.254
> +++ sbin/route/route.c26 Aug 2021 09:02:17 -
> @@ -782,6 +782,9 @@ newroute(int argc, char **argv)
>   break;
>   }
>   oerrno = errno;
> + if ((rtm_addrs & RTA_GATEWAY) == 0 &&
> + so_dst.sa.sa_family != so_gate.sa.sa_family)
> + errx(1, "address family mismatch");
>   if (!qflag && (*cmd != 'g' || ret != 0)) {
>   printf("%s %s %s", cmd, ishost ? "host" : "net", dest);
>   if (*gateway) {
> 
> Index: sys/net/rtsock.c
> ===
> RCS file: /cvs/src/sys/net/rtsock.c,v
> retrieving revision 1.319
> diff -u -p -r1.319 rtsock.c
> --- sys/net/rtsock.c  23 Jun 2021 16:10:45 -  1.319
> +++ sys/net/rtsock.c  26 Aug 2021 09:02:01 -
> @@ -822,6 +822,12 @@ route_output(struct mbuf *m, struct sock
>   error = EINVAL;
>   goto fail;
>   }
> + if ((rtm->rtm_type == RTM_ADD || rtm->rtm_type == RTM_CHANGE) &&
> + info.rti_info[RTAX_DST]->sa_family !=
> + info.rti_info[RTAX_GATEWAY]->sa_family) {
> + error = EINVAL;
> + goto fail;
> + }
> #ifdef MPLS
>   info.rti_mpls = rtm->rtm_mpls;
> #endif
> 
> 

-- 
:wq Claudio



rpki-client exclude files from rsync fetch

2021-08-31 Thread Claudio Jeker
RPKI repository can only include a few specific files, everything else is
just ignored and deleted after every fetch.  Since openrsync supports
--exclude-file now we can use this to limit what is actually accepted by
the client.

I used a config file in /etc/rpki instead of using multiple --exclude /
--include arguments. Mostly to keep the execvp argv short.

What you think?
-- 
:wq Claudio

Index: etc/Makefile
===
RCS file: /cvs/src/etc/Makefile,v
retrieving revision 1.484
diff -u -p -r1.484 Makefile
--- etc/Makefile1 May 2021 16:11:07 -   1.484
+++ etc/Makefile31 Aug 2021 12:17:40 -
@@ -156,7 +156,7 @@ distribution-etc-root-var: distrib-dirs
${DESTDIR}/etc/ppp
cd rpki; \
${INSTALL} -c -o root -g wheel -m 644 \
-   afrinic.tal apnic.tal lacnic.tal ripe.tal \
+   afrinic.tal apnic.tal lacnic.tal ripe.tal rsync.filter \
${DESTDIR}/etc/rpki
cd examples; \
${INSTALL} -c -o root -g wheel -m 644 ${EXAMPLES} \
Index: etc/rpki/rsync.filter
===
RCS file: etc/rpki/rsync.filter
diff -N etc/rpki/rsync.filter
--- /dev/null   1 Jan 1970 00:00:00 -
+++ etc/rpki/rsync.filter   31 Aug 2021 12:09:24 -
@@ -0,0 +1,7 @@
++ */
++ *.cer
++ *.crl
++ *.gbr
++ *.mft
++ *.roa
+- *
Index: usr.sbin/rpki-client/rsync.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/rsync.c,v
retrieving revision 1.24
diff -u -p -r1.24 rsync.c
--- usr.sbin/rpki-client/rsync.c19 Apr 2021 17:04:35 -  1.24
+++ usr.sbin/rpki-client/rsync.c31 Aug 2021 12:17:11 -
@@ -279,6 +279,8 @@ proc_rsync(char *prog, char *bind_addr, 
args[i++] = "--no-motd";
args[i++] = "--timeout";
args[i++] = "180";
+   args[i++] = "--exclude-from";
+   args[i++] = "/etc/rpki/rsync.filter";
if (bind_addr != NULL) {
args[i++] = "--address";
args[i++] = (char *)bind_addr;



Re: rpki-client exclude files from rsync fetch

2021-09-01 Thread Claudio Jeker
On Tue, Aug 31, 2021 at 02:23:57PM +0200, Claudio Jeker wrote:
> RPKI repository can only include a few specific files, everything else is
> just ignored and deleted after every fetch.  Since openrsync supports
> --exclude-file now we can use this to limit what is actually accepted by
> the client.
> 
> I used a config file in /etc/rpki instead of using multiple --exclude /
> --include arguments. Mostly to keep the execvp argv short.
> 
> What you think?

It seems using a config file to keep the argv list short is too
controversial and all alternate suggestions are worse.
So just add the include/exclude list as arguments.

-- 
:wq Claudio

Index: rsync.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/rsync.c,v
retrieving revision 1.24
diff -u -p -r1.24 rsync.c
--- rsync.c 19 Apr 2021 17:04:35 -  1.24
+++ rsync.c 1 Sep 2021 09:08:06 -
@@ -277,8 +277,14 @@ proc_rsync(char *prog, char *bind_addr, 
args[i++] = (char *)prog;
args[i++] = "-rt";
args[i++] = "--no-motd";
-   args[i++] = "--timeout";
-   args[i++] = "180";
+   args[i++] = "--timeout=180";
+   args[i++] = "--include=*/";
+   args[i++] = "--include=*.cer";
+   args[i++] = "--include=*.crl";
+   args[i++] = "--include=*.gbr";
+   args[i++] = "--include=*.mft";
+   args[i++] = "--include=*.roa";
+   args[i++] = "--exclude=*";
if (bind_addr != NULL) {
args[i++] = "--address";
args[i++] = (char *)bind_addr;



Re: rpki-client add http_proxy support

2021-09-01 Thread Claudio Jeker
On Wed, Sep 01, 2021 at 09:38:55AM +, Job Snijders wrote:
> On Tue, Aug 31, 2021 at 09:58:54AM +0200, Claudio Jeker wrote:
> > This diff improves the http code by a) adding an IO timeout and b)
> > implementing http_proxy support.
> > 
> > Works for me using tinyproxy as proxy server.
> 
> OK?

Already fixed :)
 
> Index: http.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
> retrieving revision 1.37
> diff -u -p -r1.37 http.c
> --- http.c1 Sep 2021 08:09:41 -   1.37
> +++ http.c1 Sep 2021 09:38:29 -
> @@ -658,7 +658,7 @@ http_new(struct http_request *req)
>   LIST_INSERT_HEAD(, conn, entry);
>   http_conn_count++;
>  
> - if (proxy.proxyhost == NULL) {
> + if (proxy.proxyhost != NULL) {
>   if (http_resolv(>res0, proxy.proxyhost,
>   proxy.proxyport) == -1) {
>   http_req_fail(req->id);
> @@ -796,7 +796,7 @@ http_connect_done(struct http_connection
>   conn->res0 = NULL;
>   conn->res = NULL;
>  
> - if (proxy.proxyhost == NULL)
> + if (proxy.proxyhost != NULL)
>   return proxy_connect(conn);
>   return http_tls_connect(conn);
>  }
> 

-- 
:wq Claudio



rpki-client add http_proxy support

2021-08-31 Thread Claudio Jeker
This diff improves the http code by a) adding an IO timeout and b)
implementing http_proxy support.

Works for me using tinyproxy as proxy server.
-- 
:wq Claudio

Index: encoding.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/encoding.c,v
retrieving revision 1.2
diff -u -p -r1.2 encoding.c
--- encoding.c  19 Apr 2021 17:04:35 -  1.2
+++ encoding.c  30 Aug 2021 19:53:47 -
@@ -64,6 +64,36 @@ fail:
return -1;
 }
 
+int
+base64_encode(const unsigned char *in, size_t inlen, char **out)
+{
+   static EVP_ENCODE_CTX *ctx;
+   unsigned char *to;
+   int tolen;
+
+   if (ctx == NULL && (ctx = EVP_ENCODE_CTX_new()) == NULL)
+   err(1, "EVP_ENCODE_CTX_new");
+
+   *out = NULL;
+
+   if (inlen >= INT_MAX / 2)
+   return -1;
+   tolen = ((inlen + 2) / 3) * 4 + 1;
+   if ((to = malloc(tolen)) == NULL)
+   return -1;
+
+   EVP_EncodeInit(ctx);
+   if (EVP_EncodeUpdate(ctx, to, , in, inlen) != 1)
+   goto fail;
+   EVP_EncodeFinal(ctx, to + tolen, );
+   *out = to;
+   return 0;
+
+fail:
+   free(to);
+   return -1;
+}
+
 /*
  * Convert binary buffer of size dsz into an upper-case hex-string.
  * Returns pointer to the newly allocated string. Function can't fail.
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.65
diff -u -p -r1.65 extern.h
--- extern.h13 Jul 2021 18:39:39 -  1.65
+++ extern.h30 Aug 2021 19:52:47 -
@@ -364,8 +364,6 @@ extern int verbose;
 
 /* Routines for RPKI entities. */
 
-int base64_decode(const unsigned char *, unsigned char **,
-   size_t *);
 voidtal_buffer(struct ibuf *, const struct tal *);
 voidtal_free(struct tal *);
 struct tal *tal_parse(const char *, char *);
@@ -499,6 +497,7 @@ void cryptoerrx(const char *, ...)
 
 int base64_decode(const unsigned char *, unsigned char **,
size_t *);
+int base64_encode(const unsigned char *, size_t, char **);
 char   *hex_encode(const unsigned char *, size_t);
 
 
Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.36
diff -u -p -r1.36 http.c
--- http.c  9 Aug 2021 10:30:23 -   1.36
+++ http.c  31 Aug 2021 07:52:16 -
@@ -70,6 +70,7 @@
 #define HTTP_USER_AGENT"OpenBSD rpki-client"
 #define HTTP_BUF_SIZE  (32 * 1024)
 #define HTTP_IDLE_TIMEOUT  10
+#define HTTP_IO_TIMEOUT(3 * 60)
 #define MAX_CONNECTIONS64
 #define NPFDS  (MAX_CONNECTIONS + 1)
 
@@ -83,6 +84,9 @@ enum http_state {
STATE_FREE,
STATE_CONNECT,
STATE_TLSCONNECT,
+   STATE_PROXY_REQUEST,
+   STATE_PROXY_STATUS,
+   STATE_PROXY_RESPONSE,
STATE_REQUEST,
STATE_RESPONSE_STATUS,
STATE_RESPONSE_HEADER,
@@ -96,9 +100,9 @@ enum http_state {
 
 struct http_proxy {
char*proxyhost;
-   char*proxyuser;
-   char*proxypw;
-};
+   char*proxyport;
+   char*proxyauth;
+} proxy;
 
 struct http_connection {
LIST_ENTRY(http_connection) entry;
@@ -116,6 +120,7 @@ struct http_connection {
size_t  bufpos;
off_t   iosz;
time_t  idle_time;
+   time_t  io_time;
int status;
int fd;
int chunked;
@@ -177,10 +182,13 @@ static enum res http_handle(struct http_
 
 /* Internal state functions used by the above functions */
 static enum reshttp_finish_connect(struct http_connection *);
+static enum resproxy_connect(struct http_connection *);
 static enum reshttp_tls_connect(struct http_connection *);
 static enum reshttp_tls_handshake(struct http_connection *);
 static enum reshttp_read(struct http_connection *);
 static enum reshttp_write(struct http_connection *);
+static enum resproxy_read(struct http_connection *);
+static enum resproxy_write(struct http_connection *);
 static enum resdata_write(struct http_connection *);
 
 static time_t
@@ -277,6 +285,138 @@ url_encode(const char *path)
return (epath);
 }
 
+static char
+hextochar(const char *str)
+{
+   unsigned char c, ret;
+
+   c = str[0];
+   ret = c;
+   if (isalpha(c))
+   ret -= isupper(c) ? 'A' - 10 : 'a' - 10;
+   else
+   ret -= '0';
+   ret *= 16;
+
+   c = str[1];
+   ret += c;
+   if (isalpha(c))
+   ret -= isupper(c) ? 'A' - 10 : 'a' - 10;
+   else
+   ret -= '0';
+   return 

Re: bgpd MRT RFC8050 support (add-path for mrt dumps)

2021-08-18 Thread Claudio Jeker
On Mon, Aug 09, 2021 at 12:17:47PM +0200, Claudio Jeker wrote:
> This diff adds the bits needed to support add-path in MRT dumps.
> The problem here is that MRT as a stateless protocol has no chance
> to know what kind of encoding (add-path or not) is used for the NLRI in
> message dumps. And for table dumps there is a need to add an extra field
> to the dumps to show the path-id.
> 
> There are two issues:
> - for message dumps: it is necessary to peek into UPDATE messages to
>   figure out if that update is using add-path or not. This comes from the
>   fact that the add-path RFC allows to set the option per AFI/SAFI and
>   also per direction. This is a major pain in bgpd since UPDATE messages
>   are actually parsed in the RDE and not in the SE. The SE just does the
>   basic lenght checks (header size, total length). So this peak into the
>   packet needs to be done with some care (especialy for MP encoded
>   UPDATEs).
> 
> - for table dumps the RFC did a major fobar and defined a extra special
>   encoding for non-IPv4/IPv6 prefixes. In the general encoding the path-id
>   is not part of the rib entries sub-struct but is instead part of the
>   NLRI. This encoding is to complex to build into the bgpd codebase and it
>   seems the only other BGP implementation supporting RIB_GENERIC_ADDPATH,
>   gobgp, is also not implementing it according to the RFC but instead is
>   using the same encoding as for the other _ADDPATH types. OpenBGPD will
>   do the same.
> 
> This seems to work for me and results in the right output in bgpctl.
> 
> Please review mrt_bgp_guess_aid() and check if all checks are correct to
> ensure we don't run off the rails.

Ping

-- 
:wq Claudio

Index: mrt.c
===
RCS file: /cvs/src/usr.sbin/bgpd/mrt.c,v
retrieving revision 1.104
diff -u -p -r1.104 mrt.c
--- mrt.c   24 Jun 2021 10:04:05 -  1.104
+++ mrt.c   9 Aug 2021 10:13:43 -
@@ -91,23 +91,128 @@ int mrt_open(struct mrt *, time_t);
x == MRT_TABLE_DUMP_V2) ? RDEIDX : SEIDX\
)
 
-void
-mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen,
-struct peer *peer)
+static u_int8_t
+mrt_bgp_guess_aid(u_int8_t *pkg, u_int16_t pkglen)
+{
+   u_int16_t wlen, alen, len, afi;
+   u_int8_t type, aid;
+
+   pkg += MSGSIZE_HEADER;
+   pkglen -= MSGSIZE_HEADER;
+
+   if (pkglen < 4)
+   goto bad;
+
+   memcpy(, pkg, 2);
+   wlen = ntohs(wlen);
+   pkg += 2;
+   pkglen -= 2;
+
+   memcpy(, pkg, 2);
+   alen = ntohs(alen);
+   pkg += 2;
+   pkglen -= 2;
+
+   if (wlen > 0 || alen < pkglen || (wlen == 0 && alen == 0)) {
+   /* UPDATE has withdraw or NLRI prefixes or IPv4 EoR */
+   return AID_INET;
+   }
+
+   /* bad attribute length */
+   if (alen > pkglen)
+   goto bad;
+
+   /* try to extract AFI/SAFI from the MP attributes */
+   while (alen > 0) {
+   if (alen < 3)
+   goto bad;
+   type = pkg[1];
+   if (pkg[0] & ATTR_EXTLEN) {
+   if (alen < 4)
+   goto bad;
+   memcpy(, pkg + 2, 2);
+   len = ntohs(len);
+   pkg += 4;
+   alen -= 4;
+   } else {
+   len = pkg[2];
+   pkg += 3;
+   alen -= 3;
+   }
+   if (len > alen)
+   goto bad;
+
+   if (type == ATTR_MP_REACH_NLRI ||
+   type == ATTR_MP_UNREACH_NLRI) {
+   if (alen < 3)
+   goto bad;
+   memcpy(, pkg, 2);
+   afi = ntohs(afi);
+   if (afi2aid(afi, pkg[2], ) == -1)
+   goto bad;
+   return aid;
+   }
+
+   pkg += len;
+   alen -= len;
+   }
+
+bad:
+   return AID_UNSPEC;
+}
+
+static u_int16_t
+mrt_bgp_msg_subtype(struct mrt *mrt, void *pkg, u_int16_t pkglen,
+struct peer *peer, enum msg_type msgtype, int in)
 {
-   struct ibuf *buf;
-   int  incoming = 0;
u_int16_tsubtype = BGP4MP_MESSAGE;
+   u_int8_t aid, mask;
 
if (peer->capa.neg.as4byte)
subtype = BGP4MP_MESSAGE_AS4;
 
+   if (msgtype != UPDATE)
+   return subtype;
+
+   /*
+* RFC8050 adjust types for add-path enabled sessions.
+* It is necessary to extract the AID from UPDATES to decide
+* if the add-path types are needed or not. The ADDPATH
+* subtypes only matter for BGP UPDATES.
+  

rpki-client add back keep-alive to http requests

2021-09-09 Thread Claudio Jeker
While Connection: keep-alive should be the default it seems that at least
some of the CA repositories fail to behave like that. Adding back the
Connection header seems to fix this and delta downloads go faster again.

-- 
:wq Claudio

Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.38
diff -u -p -r1.38 http.c
--- http.c  1 Sep 2021 09:39:14 -   1.38
+++ http.c  9 Sep 2021 07:26:35 -
@@ -1026,6 +1026,7 @@ http_request(struct http_connection *con
conn->bufpos = 0;
if ((r = asprintf(>buf,
"GET /%s HTTP/1.1\r\n"
+   "Connection: keep-alive\r\n"
"Host: %s\r\n"
"Accept-Encoding: identity\r\n"
"User-Agent: " HTTP_USER_AGENT "\r\n"



rpki-client compare oid with OBJ_cmp

2021-09-09 Thread Claudio Jeker
Trying to remove work that is done over and over again.
One of those checks are the various OID compares.
Instead of converting the ASN1_OBJECT into a string and comparing the
strings, convert the string into an ASN1_OBJECT once and then compare
these objects with OBJ_cmp().

Any comments about this?
-- 
:wq Claudio

Index: cert.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.31
diff -u -p -r1.31 cert.c
--- cert.c  13 Jul 2021 18:39:39 -  1.31
+++ cert.c  9 Sep 2021 12:25:47 -
@@ -46,6 +46,21 @@ struct   parse {
const char  *fn; /* currently-parsed file */
 };
 
+static ASN1_OBJECT *carepo_oid;/* 1.3.6.1.5.5.7.48.5 (caRepository) */
+static ASN1_OBJECT *mft_oid;   /* 1.3.6.1.5.5.7.48.10 (rpkiManifest) */
+static ASN1_OBJECT *notify_oid;/* 1.3.6.1.5.5.7.48.13 (rpkiNotify) */
+
+static void
+cert_init_oid(void)
+{
+   if ((carepo_oid = OBJ_txt2obj("1.3.6.1.5.5.7.48.5", 1)) == NULL)
+   errx(1, "OBJ_txt2obj for %s failed", "1.3.6.1.5.5.7.48.5");
+   if ((mft_oid = OBJ_txt2obj("1.3.6.1.5.5.7.48.10", 1)) == NULL)
+   errx(1, "OBJ_txt2obj for %s failed", "1.3.6.1.5.5.7.48.10");
+   if ((notify_oid = OBJ_txt2obj("1.3.6.1.5.5.7.48.13", 1)) == NULL)
+   errx(1, "OBJ_txt2obj for %s failed", "1.3.6.1.5.5.7.48.13");
+}
+
 /*
  * Append an IP address structure to our list of results.
  * This will also constrain us to having at most one inheritence
@@ -207,9 +222,9 @@ sbgp_sia_resource_entry(struct parse *p,
const unsigned char *d, size_t dsz)
 {
ASN1_SEQUENCE_ANY   *seq;
+   ASN1_OBJECT *oid;
const ASN1_TYPE *t;
int  rc = 0, ptag;
-   char buf[128];
long plen;
 
if ((seq = d2i_ASN1_SEQUENCE_ANY(NULL, , dsz)) == NULL) {
@@ -233,7 +248,7 @@ sbgp_sia_resource_entry(struct parse *p,
p->fn, ASN1_tag2str(t->type), t->type);
goto out;
}
-   OBJ_obj2txt(buf, sizeof(buf), t->value.object, 1);
+   oid = t->value.object;
 
t = sk_ASN1_TYPE_value(seq, 1);
if (t->type != V_ASN1_OTHER) {
@@ -257,11 +272,14 @@ sbgp_sia_resource_entry(struct parse *p,
 *  - 1.3.6.1.5.5.7.48.10 (rpkiManifest)
 *  - 1.3.6.1.5.5.7.48.13 (rpkiNotify)
 */
-   if (strcmp(buf, "1.3.6.1.5.5.7.48.5") == 0)
+   if (carepo_oid == NULL)
+   cert_init_oid();
+
+   if (OBJ_cmp(oid, carepo_oid) == 0)
rc = sbgp_sia_resource_carepo(p, d, plen);
-   else if (strcmp(buf, "1.3.6.1.5.5.7.48.10") == 0)
+   else if (OBJ_cmp(oid, mft_oid) == 0)
rc = sbgp_sia_resource_mft(p, d, plen);
-   else if (strcmp(buf, "1.3.6.1.5.5.7.48.13") == 0)
+   else if (OBJ_cmp(oid, notify_oid) == 0)
rc = sbgp_sia_resource_notify(p, d, plen);
else
rc = 1; /* silently ignore */
Index: cms.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/cms.c,v
retrieving revision 1.9
diff -u -p -r1.9 cms.c
--- cms.c   13 Jul 2021 18:39:39 -  1.9
+++ cms.c   9 Sep 2021 12:25:47 -
@@ -35,16 +35,15 @@
  * Return the eContent as a string and set "rsz" to be its length.
  */
 unsigned char *
-cms_parse_validate(X509 **xp, const char *fn,
-const char *oid, size_t *rsz)
+cms_parse_validate(X509 **xp, const char *fn, const ASN1_OBJECT *oid,
+size_t *rsz)
 {
const ASN1_OBJECT   *obj;
ASN1_OCTET_STRING   **os = NULL;
BIO *bio = NULL;
CMS_ContentInfo *cms;
FILE*f;
-   char buf[128];
-   int  rc = 0, sz;
+   int  rc = 0;
STACK_OF(X509)  *certs = NULL;
unsigned char   *res = NULL;
 
@@ -84,16 +83,12 @@ cms_parse_validate(X509 **xp, const char
/* RFC 6488 section 2.1.3.1: check the object's eContentType. */
 
obj = CMS_get0_eContentType(cms);
-   if ((sz = OBJ_obj2txt(buf, sizeof(buf), obj, 1)) < 0)
-   cryptoerrx("OBJ_obj2txt");
-
-   if ((size_t)sz >= sizeof(buf)) {
-   warnx("%s: RFC 6488 section 2.1.3.1: "
-   "eContentType: OID too long", fn);
-   goto out;
-   } else if (strcmp(buf, oid)) {
+   if (OBJ_cmp(obj, oid) != 0) {
+   char buf[128], obuf[128];
+   OBJ_obj2txt(buf, sizeof(buf), obj, 1);
+   OBJ_obj2txt(obuf, sizeof(obuf), oid, 1);
warnx("%s: RFC 6488 section 2.1.3.1: eContentType: "
-   "unknown OID: %s, want %s", fn, buf, oid);
+   "unknown OID: %s, want %s", fn, buf, obuf);
goto out;
}
 
Index: 

Re: iked(8): make proto option accept lists

2021-09-03 Thread Claudio Jeker
On Fri, Sep 03, 2021 at 10:12:57AM +0200, Sebastian Benoit wrote:
> Tobias Heider(tobias.hei...@stusta.de) on 2021.09.02 15:39:46 +0200:
> > The diff below makes iked accept a list of protocols for the "proto" config
> > option in iked.conf(5).
> > This would allow us to have a single policy with "proto { ipencap, ipv6 }"
> > to secure a gif(4) tunnel, instead of requiring one policy for each 
> > protocol.
> > 
> > ok?
> 
> I only gave the parser bits a quick read.
> 
> The manpage change would be nice to compare the parser with what you
> document.
> 
> A bit more below.
>  
> > Index: iked.h
> > ===
> > RCS file: /cvs/src/sbin/iked/iked.h,v
> > retrieving revision 1.193
> > diff -u -p -r1.193 iked.h
> > --- iked.h  1 Sep 2021 15:30:06 -   1.193
> > +++ iked.h  2 Sep 2021 13:37:21 -
> > @@ -242,10 +242,9 @@ struct iked_policy {
> >  
> >  #define IKED_SKIP_FLAGS 0
> >  #define IKED_SKIP_AF1
> > -#define IKED_SKIP_PROTO 2
> > -#define IKED_SKIP_SRC_ADDR  3
> > -#define IKED_SKIP_DST_ADDR  4
> > -#define IKED_SKIP_COUNT 5
> > +#define IKED_SKIP_SRC_ADDR  2
> > +#define IKED_SKIP_DST_ADDR  3
> > +#define IKED_SKIP_COUNT 4
> > struct iked_policy  *pol_skip[IKED_SKIP_COUNT];
> >  
> > uint8_t  pol_flags;
> > @@ -265,7 +264,8 @@ struct iked_policy {
> > int  pol_af;
> > int  pol_rdomain;
> > uint8_t  pol_saproto;
> > -   unsigned int pol_ipproto;
> > +   unsigned int pol_ipproto[IKED_IPPROTO_MAX];
> > +   unsigned int pol_nipproto;
> >  
> > struct iked_addr pol_peer;
> > struct iked_static_idpol_peerid;
> > Index: parse.y
> > ===
> > RCS file: /cvs/src/sbin/iked/parse.y,v
> > retrieving revision 1.131
> > diff -u -p -r1.131 parse.y
> > --- parse.y 28 May 2021 18:01:39 -  1.131
> > +++ parse.y 2 Sep 2021 13:37:21 -
> > @@ -374,7 +374,7 @@ void copy_transforms(unsigned int,
> > const struct ipsec_xf **, unsigned int,
> > struct iked_transform **, unsigned int *,
> > struct iked_transform *, size_t);
> > -int create_ike(char *, int, uint8_t,
> > +int create_ike(char *, int, struct ipsec_addr_wrap 
> > *,
> > int, struct ipsec_hosts *,
> > struct ipsec_hosts *, struct ipsec_mode *,
> > struct ipsec_mode *, uint8_t,
> > @@ -388,9 +388,9 @@ uint8_t  x2i(unsigned char *);
> >  int parsekey(unsigned char *, size_t, struct 
> > iked_auth *);
> >  int parsekeyfile(char *, struct iked_auth *);
> >  voidiaw_free(struct ipsec_addr_wrap *);
> > -static int  create_flow(struct iked_policy *pol, struct 
> > ipsec_addr_wrap *ipa,
> > +static int  create_flow(struct iked_policy *pol, int, struct 
> > ipsec_addr_wrap *ipa,
> > struct ipsec_addr_wrap *ipb);
> > -static int  expand_flows(struct iked_policy *, struct 
> > ipsec_addr_wrap *,
> > +static int  expand_flows(struct iked_policy *, int, struct 
> > ipsec_addr_wrap *,
> > struct ipsec_addr_wrap *);
> >  static struct ipsec_addr_wrap *
> >  expand_keyword(struct ipsec_addr_wrap *);
> > @@ -407,7 +407,6 @@ typedef struct {
> > uint8_t  ikemode;
> > uint8_t  dir;
> > uint8_t  satype;
> > -   uint8_t  proto;
> > char*string;
> > uint16_t port;
> > struct ipsec_hosts  *hosts;
> > @@ -415,6 +414,7 @@ typedef struct {
> > struct ipsec_addr_wrap  *anyhost;
> > struct ipsec_addr_wrap  *host;
> > struct ipsec_addr_wrap  *cfg;
> > +   struct ipsec_addr_wrap  *proto;
> > struct {
> > char*srcid;
> > char*dstid;
> > @@ -449,8 +449,7 @@ typedef struct {
> >  %token   NUMBER
> >  %typestring
> >  %typesatype
> > -%type proto
> > -%typeprotoval
> > +%type proto proto_list protoval
> >  %type hosts hosts_list
> >  %type  port
> >  %typeportval af rdomain
> > @@ -632,8 +631,21 @@ af : /* empty */ 

Re: rpki-client add back keep-alive to http requests

2021-09-10 Thread Claudio Jeker
On Thu, Sep 09, 2021 at 09:18:04AM -0600, Bob Beck wrote:
> 
> ok beck@
> 
> On Thu, Sep 09, 2021 at 09:35:51AM +0200, Claudio Jeker wrote:
> > While Connection: keep-alive should be the default it seems that at least
> > some of the CA repositories fail to behave like that. Adding back the
> > Connection header seems to fix this and delta downloads go faster again.
> > 

After further inspection of the code and the HTTP/1.1 RFC I came to the
conclusion that the code is wrong. For HTTP/1.1 the default should be
keep-alive being on. For non-HTTP/1.1 (aka HTTP/1.0 there is no other 1.X
spec) keep-alive should be off by default.

So look at the HTTP protocol header and set keep-alive then. This seems to
work. Also check for Connection: close. At least one server sends a
Connection: close header after a bunch of requests.

So this is a better fix for the keep-alive issue.
-- 
:wq Claudio

Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.38
diff -u -p -r1.38 http.c
--- http.c  1 Sep 2021 09:39:14 -   1.38
+++ http.c  10 Sep 2021 10:02:12 -
@@ -1053,11 +1053,16 @@ http_request(struct http_connection *con
 static int
 http_parse_status(struct http_connection *conn, char *buf)
 {
+#define HTTP_11"HTTP/1.1 "
const char *errstr;
char *cp, ststr[4];
char gerror[200];
int status;
 
+   /* Check if the protocol is 1.1 and enable keep-alive in that case */
+   if (strncmp(buf, HTTP_11, strlen(HTTP_11)) == 0)
+   conn->keep_alive = 1;
+
cp = strchr(buf, ' ');
if (cp == NULL) {
warnx("Improper response from %s", http_info(conn->host));
@@ -1226,7 +1231,9 @@ http_parse_header(struct http_connection
} else if (strncasecmp(cp, CONNECTION, sizeof(CONNECTION) - 1) == 0) {
cp += sizeof(CONNECTION) - 1;
cp[strcspn(cp, " \t")] = '\0';
-   if (strcasecmp(cp, "keep-alive") == 0)
+   if (strcasecmp(cp, "close") == 0)
+   conn->keep_alive = 0;
+   else if (strcasecmp(cp, "keep-alive") == 0)
conn->keep_alive = 1;
} else if (strncasecmp(cp, LAST_MODIFIED,
sizeof(LAST_MODIFIED) - 1) == 0) {



rpki-client RRDP delta vs snapshot sync

2021-09-14 Thread Claudio Jeker
I'm tired waiting 30min and more for apnic and idnic to finish their delta
syncs with 1000+ deltas to fetch from a server on the other side of the
planet. If a repo is more than 300 deltas behind just grab the snapshot,
it is way faster in the end.

The number 300 was selected to be not too low to allow repos to mostly use
the delta downloads and save bandwidth.

-- 
:wq Claudio

Index: rrdp_notification.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/rrdp_notification.c,v
retrieving revision 1.6
diff -u -p -r1.6 rrdp_notification.c
--- rrdp_notification.c 12 Aug 2021 15:23:16 -  1.6
+++ rrdp_notification.c 10 Sep 2021 13:16:23 -
@@ -371,6 +371,10 @@ notification_done(struct notification_xm
return NOTIFICATION;
}
 
+   /* it makes no sense to process too many deltas */
+   if (nxml->serial - nxml->repository->serial > 300)
+   goto snapshot;
+
/* check that all needed deltas are available */
s = nxml->repository->serial + 1;
TAILQ_FOREACH(d, >delta_q, q) {



Re: Change vm_dsize to vsize_t

2021-09-07 Thread Claudio Jeker
On Mon, Sep 06, 2021 at 12:39:56PM -0700, Greg Steuck wrote:
> In the course of making ASan work on OpenBSD I ran into an accounting
> limitation. struct vmspace declares vm_dsize as segsz_t (aka int32_t).
> This effectively limits it to 2^31 pages (2^43 bytes on amd64). This
> would be enough if didn't also count sparse allocation.
> 
> ASan allocates 1/8th of the process address space as shadow memory. It
> is very sparsely populated, still given VM_MAXUSER_ADDRESS value of
> 0x7f7fc000, it goes up to 2^47 bytes which then requires 2^44
> bytes of shadow. So, it won't fit.
> 
> Hence the following unfinished patch which allows simple ASan'd programs
> to detect memory errors. If people don't see an alternative solution,
> I'll fix up the users of kinfo_proc.p_vm_dsize and we can decide
> when/how this should land.
> 
> From 42c776531620e9baa6735da71349c3c045fb64d8 Mon Sep 17 00:00:00 2001
> From: Greg Steuck 
> Date: Sun, 5 Sep 2021 13:28:43 -0700
> Subject: [PATCH] Change struct vmspace to use vsize_t vm_dused
> 
> This was overflowing given high MAXDSIZ. This is very appropriate given
> that the field is usually incremented by a value returned by
> uvmspace_dused which returns vsize_t.
> 
> The change is not finished, only kernel is fixed so far. Userspace
> tools consuming p_vm_dsize from kinfo_proc are likely not correct.
> ---
>  sys/sys/sysctl.h | 2 +-
>  sys/uvm/uvm_extern.h | 2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
> index afdc0689dee..868ef82c696 100644
> --- a/sys/sys/sysctl.h
> +++ b/sys/sys/sysctl.h
> @@ -443,7 +443,7 @@ struct kinfo_proc {
>  
>   int32_t p_vm_rssize;/* SEGSZ_T: current resident set size 
> in pages */
>   int32_t p_vm_tsize; /* SEGSZ_T: text size (pages) */
> - int32_t p_vm_dsize; /* SEGSZ_T: data size (pages) */
> + u_int64_t   p_vm_dsize; /* VSIZE_T: data size (pages) */
>   int32_t p_vm_ssize; /* SEGSZ_T: stack size (pages) */
>  
>   int64_t p_uvalid;   /* CHAR: following p_u* members from 
> struct user are valid */

>From my understanding this is not how struct kinfo_proc should be modified.
Instead the code should add the u_int64_t version at the end and leave the
old in place. This way old userland still works with new kernel.

> diff --git a/sys/uvm/uvm_extern.h b/sys/uvm/uvm_extern.h
> index faa4a2e5449..ebc74d97917 100644
> --- a/sys/uvm/uvm_extern.h
> +++ b/sys/uvm/uvm_extern.h
> @@ -207,7 +207,7 @@ struct vmspace {
>   segsz_t vm_swrss;   /* resident set size before last swap */
>   segsz_t vm_tsize;   /* text size (pages) XXX */
>   segsz_t vm_dsize;   /* data size (pages) XXX */
> - segsz_t vm_dused;   /* data segment length (pages) XXX */
> + vsize_t vm_dused;   /* data segment length (pages) XXX */
>   segsz_t vm_ssize;   /* [v] stack size (pages) */
>   caddr_t vm_taddr;   /* [I] user virtual address of text */
>   caddr_t vm_daddr;   /* [I] user virtual address of data */
> -- 
> 2.33.0
> 

-- 
:wq Claudio



do less recallocarray calls in rpki-client

2021-09-08 Thread Claudio Jeker
Looking at profiling information and the code made me realize that these
recallocarray calls growing the array by one every time are unnecessary.
The size of the array is known in advance so use that information and
build it up ahead of time.

In the roa case the IP list is double nested and so one still needs to
resize the array but for mft the file-and-hash list is only defined once
per MFT and so calloc can be used there.

Works for me, the speed-up is not really noticable but I think this change
is still worth it.
-- 
:wq Claudio

Index: roa.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
retrieving revision 1.23
diff -u -p -r1.23 roa.c
--- roa.c   1 Aug 2021 22:29:49 -   1.23
+++ roa.c   7 Sep 2021 13:19:19 -
@@ -109,10 +109,6 @@ roa_parse_addr(const ASN1_OCTET_STRING *
}
}
 
-   p->res->ips = recallocarray(p->res->ips, p->res->ipsz, p->res->ipsz + 1,
-   sizeof(struct roa_ip));
-   if (p->res->ips == NULL)
-   err(1, NULL);
res = >res->ips[p->res->ipsz++];
 
res->addr = addr;
@@ -180,6 +176,12 @@ roa_parse_ipfam(const ASN1_OCTET_STRING 
"failed ASN.1 sequence parse", p->fn);
goto out;
}
+
+   /* will be called multiple times so use recallocarray */
+   p->res->ips = recallocarray(p->res->ips, p->res->ipsz,
+   p->res->ipsz + sk_ASN1_TYPE_num(sseq), sizeof(struct roa_ip));
+   if (p->res->ips == NULL)
+   err(1, NULL);
 
for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) {
t = sk_ASN1_TYPE_value(sseq, i);
Index: mft.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
retrieving revision 1.36
diff -u -p -r1.36 mft.c
--- mft.c   13 Jul 2021 18:39:39 -  1.36
+++ mft.c   7 Sep 2021 12:59:57 -
@@ -194,12 +194,6 @@ mft_parse_filehash(struct parse *p, cons
}
 
/* Insert the filename and hash value. */
-
-   p->res->files = recallocarray(p->res->files, p->res->filesz,
-   p->res->filesz + 1, sizeof(struct mftfile));
-   if (p->res->files == NULL)
-   err(1, NULL);
-
fent = >res->files[p->res->filesz++];
 
fent->file = fn;
@@ -231,6 +225,10 @@ mft_parse_flist(struct parse *p, const A
"failed ASN.1 sequence parse", p->fn);
goto out;
}
+
+   p->res->files = calloc(sk_ASN1_TYPE_num(seq), sizeof(struct mftfile));
+   if (p->res->files == NULL)
+   err(1, NULL);
 
for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
t = sk_ASN1_TYPE_value(seq, i);



Re: tls_pending(3)

2021-09-16 Thread Claudio Jeker
On Thu, Sep 16, 2021 at 11:00:31PM +0200, Kristaps Dzonsons wrote:
> Hi,
> 
> I'm porting a nonblocking, polling OpenSSL system to libtls.  However, I'm
> not sure how this is non-hackily possible without SSL_pending(3) to detect
> if less data is read with tls_read() than is buffered.
> 
>  writer:
>   tls_write(40)
> 
>  reader:
>   poll(POLLIN, INFTIM) -> POLLIN /* descriptor has a read */
>   tls_read(20) /* 20 bytes read, 20 bytes remain */
>   poll(POLLIN, INFTIM) -> 0 /* data was buffered */
> 
> This introduces tls_pending(3), which calls through to SSL_pending(3), and
> includes a simple example in tls_read(3).
> 
> Beck's tutorial says that "libtls is designed to do the common things you do
> for making TLS connections easy", and I'm not sure my use case meets that
> standard.  If it looks reasonable, however, I can also add the regression
> tests.

In general you should call tls_read() until it retruns TLS_WANT_POLL*.
Then you poll again. So you need to adapt the poll loop a bit but in most
cases this is not hard to do.
 
> Thank you,
> 
> Kristaps

> Index: tls.c
> ===
> RCS file: /cvs/src/lib/libtls/tls.c,v
> retrieving revision 1.89
> diff -u -p -r1.89 tls.c
> --- tls.c 1 Feb 2021 15:35:41 -   1.89
> +++ tls.c 16 Sep 2021 20:57:32 -
> @@ -788,6 +788,16 @@ tls_handshake(struct tls *ctx)
>   return (rv);
>  }
>  
> +size_t
> +tls_pending(const struct tls *ctx)
> +{
> + 
> + if ((ctx->state & TLS_HANDSHAKE_COMPLETE) != 0)
> + return 0;
> +
> + return (size_t)SSL_pending(ctx->ssl_conn);
> +}
> +
>  ssize_t
>  tls_read(struct tls *ctx, void *buf, size_t buflen)
>  {
> Index: tls.h
> ===
> RCS file: /cvs/src/lib/libtls/tls.h,v
> retrieving revision 1.58
> diff -u -p -r1.58 tls.h
> --- tls.h 22 Jan 2020 06:44:02 -  1.58
> +++ tls.h 16 Sep 2021 20:57:32 -
> @@ -177,6 +177,7 @@ int tls_connect_socket(struct tls *_ctx,
>  int tls_connect_cbs(struct tls *_ctx, tls_read_cb _read_cb,
>  tls_write_cb _write_cb, void *_cb_arg, const char *_servername);
>  int tls_handshake(struct tls *_ctx);
> +size_t tls_pending(const struct tls *_ctx);
>  ssize_t tls_read(struct tls *_ctx, void *_buf, size_t _buflen);
>  ssize_t tls_write(struct tls *_ctx, const void *_buf, size_t _buflen);
>  int tls_close(struct tls *_ctx);
> Index: man/tls_read.3
> ===
> RCS file: /cvs/src/lib/libtls/man/tls_read.3,v
> retrieving revision 1.7
> diff -u -p -r1.7 tls_read.3
> --- man/tls_read.39 Jul 2019 17:58:33 -   1.7
> +++ man/tls_read.316 Sep 2021 20:57:32 -
> @@ -27,6 +27,7 @@
>  .Nm tls_handshake ,
>  .Nm tls_error ,
>  .Nm tls_close ,
> +.Nm tls_pending ,
>  .Nm tls_reset
>  .Nd use a TLS connection
>  .Sh SYNOPSIS
> @@ -51,6 +52,8 @@
>  .Fn tls_close "struct tls *ctx"
>  .Ft void
>  .Fn tls_reset "struct tls *ctx"
> +.Ft size_t
> +.Fn tls_pending "const struct tls *ctx"
>  .Sh DESCRIPTION
>  .Fn tls_read
>  reads
> @@ -58,6 +61,8 @@ reads
>  bytes of data from the socket into
>  .Fa buf .
>  It returns the amount of data read.
> +.Fn tls_pending
> +returns the number of bytes that may be read without blocking.
>  .Pp
>  .Fn tls_write
>  writes
> @@ -99,6 +104,9 @@ and
>  .Fn tls_write
>  return a size on success or -1 on error.
>  .Pp
> +.Fn tls_pending
> +returns a size or zero if no data is buffered for immediate reading.
> +.Pp
>  .Fn tls_handshake
>  and
>  .Fn tls_close
> @@ -198,6 +206,28 @@ while (len > 0) {
>   buf += ret;
>   len -= ret;
>   }
> + }
> +}
> +\&...
> +.Ed
> +.Pp
> +For non-blocking input, the following example demonstrates how to handle
> +buffered data when the descriptor may have none to read:
> +.Bd -literal -offset indent
> +\&...
> +pfd[0].fd = fd;
> +pfd[0].events = POLLIN;
> +for (;;) {
> + int timeo;
> +
> + timeo = tls_pending(tls) ? 0 : INFTIM;
> + if (poll(pfd, 1, timeo) == -1)
> + err(1, "poll");
> + if ((pfd[0].revents & POLLIN) || tls_pending(tls)) {
> + ssize_t ret;
> +
> + ret = tls_read(ctx, buf, len);
> + \&...
>   }
>  }
>  \&...


-- 
:wq Claudio



Re: do less recallocarray calls in rpki-client

2021-09-08 Thread Claudio Jeker
On Wed, Sep 08, 2021 at 05:40:31PM +0200, Theo Buehler wrote:
> On Wed, Sep 08, 2021 at 03:05:41PM +0200, Claudio Jeker wrote:
> > Looking at profiling information and the code made me realize that these
> > recallocarray calls growing the array by one every time are unnecessary.
> > The size of the array is known in advance so use that information and
> > build it up ahead of time.
> > 
> > In the roa case the IP list is double nested and so one still needs to
> > resize the array but for mft the file-and-hash list is only defined once
> > per MFT and so calloc can be used there.
> > 
> > Works for me, the speed-up is not really noticable but I think this change
> > is still worth it.
> 
> I'm ok with this.
> 
> Should we assert after the for loops that we added as many filehashes or
> addresses as allocated? This is currently more obvious than after this
> change.

Hmm. The code is correct even if it loads less elements. It will
overallocate but with NULL. Also currently the code fails hard if an
element does not parse. So not sure about that.
 
> > -- 
> > :wq Claudio
> > 
> > Index: roa.c
> > ===
> > RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
> > retrieving revision 1.23
> > diff -u -p -r1.23 roa.c
> > --- roa.c   1 Aug 2021 22:29:49 -   1.23
> > +++ roa.c   7 Sep 2021 13:19:19 -
> > @@ -109,10 +109,6 @@ roa_parse_addr(const ASN1_OCTET_STRING *
> > }
> > }
> >  
> > -   p->res->ips = recallocarray(p->res->ips, p->res->ipsz, p->res->ipsz + 1,
> > -   sizeof(struct roa_ip));
> > -   if (p->res->ips == NULL)
> > -   err(1, NULL);
> > res = >res->ips[p->res->ipsz++];
> >  
> > res->addr = addr;
> > @@ -180,6 +176,12 @@ roa_parse_ipfam(const ASN1_OCTET_STRING 
> > "failed ASN.1 sequence parse", p->fn);
> > goto out;
> > }
> > +
> > +   /* will be called multiple times so use recallocarray */
> > +   p->res->ips = recallocarray(p->res->ips, p->res->ipsz,
> > +   p->res->ipsz + sk_ASN1_TYPE_num(sseq), sizeof(struct roa_ip));
> > +   if (p->res->ips == NULL)
> > +   err(1, NULL);
> >  
> > for (i = 0; i < sk_ASN1_TYPE_num(sseq); i++) {
> > t = sk_ASN1_TYPE_value(sseq, i);
> > Index: mft.c
> > ===
> > RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v
> > retrieving revision 1.36
> > diff -u -p -r1.36 mft.c
> > --- mft.c   13 Jul 2021 18:39:39 -  1.36
> > +++ mft.c   7 Sep 2021 12:59:57 -
> > @@ -194,12 +194,6 @@ mft_parse_filehash(struct parse *p, cons
> > }
> >  
> > /* Insert the filename and hash value. */
> > -
> > -   p->res->files = recallocarray(p->res->files, p->res->filesz,
> > -   p->res->filesz + 1, sizeof(struct mftfile));
> > -   if (p->res->files == NULL)
> > -   err(1, NULL);
> > -
> > fent = >res->files[p->res->filesz++];
> >  
> > fent->file = fn;
> > @@ -231,6 +225,10 @@ mft_parse_flist(struct parse *p, const A
> > "failed ASN.1 sequence parse", p->fn);
> > goto out;
> > }
> > +
> > +   p->res->files = calloc(sk_ASN1_TYPE_num(seq), sizeof(struct mftfile));
> > +   if (p->res->files == NULL)
> > +   err(1, NULL);
> >  
> > for (i = 0; i < sk_ASN1_TYPE_num(seq); i++) {
> > t = sk_ASN1_TYPE_value(seq, i);
> > 
> 
> 

-- 
:wq Claudio



bgpctl add support for RFC8050 (add-path support for MRT parser)

2021-07-13 Thread Claudio Jeker
This diff adds support to read MRT files using the new introduced _ADDPATH
types as defined in RFC8050. I also started adding MRT support to bgpd but
that depends on ADD-PATH itself.

There are a few gotchas, especially the MRT_DUMP_V2 RIB_GENERIC_ADDPATH
handling is different from all other RIB entry handling. This is a major
pain point for bgpd less so for the bgpctl parser.

Some MRT update dumps that can be downloaded and use ADDPATH do actually
use the BGP4MP_MESSAGE _ADDPATH variant for non-addpath enabled sessions.
The update messages can not be parsed because the NLRI encoding is incorrect.

I tested with a few RIB and UPDATE dumps from RIS, route-views and other
open collectors and it works for me.
-- 
:wq Claudio

Index: usr.sbin/bgpctl/bgpctl.c
===
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.269
diff -u -p -r1.269 bgpctl.c
--- usr.sbin/bgpctl/bgpctl.c16 Jun 2021 16:24:11 -  1.269
+++ usr.sbin/bgpctl/bgpctl.c13 Jul 2021 13:20:51 -
@@ -470,7 +470,7 @@ show(struct imsg *imsg, struct parse_res
warnx("bad IMSG_CTL_SHOW_RIB_ATTR received");
break;
}
-   output->attr(imsg->data, ilen, res->flags);
+   output->attr(imsg->data, ilen, res->flags, 0);
break;
case IMSG_CTL_SHOW_RIB_MEM:
if (imsg->hdr.len < IMSG_HEADER_SIZE + sizeof(stats))
@@ -1150,6 +1150,10 @@ show_mrt_dump(struct mrt_rib *mr, struct
ctl.local_pref = mre->local_pref;
ctl.med = mre->med;
/* weight is not part of the mrt dump so it can't be set */
+   if (mr->add_path) {
+   ctl.flags |= F_PREF_PATH_ID;
+   ctl.path_id = mre->path_id;
+   }
 
if (mre->peer_idx < mp->npeers) {
ctl.remote_addr = mp->peers[mre->peer_idx].addr;
@@ -1195,7 +1199,7 @@ show_mrt_dump(struct mrt_rib *mr, struct
if (req->flags & F_CTL_DETAIL) {
for (j = 0; j < mre->nattrs; j++)
output->attr(mre->attrs[j].attr,
-   mre->attrs[j].attr_len, req->flags);
+   mre->attrs[j].attr_len, req->flags, 0);
}
}
 }
@@ -1211,6 +1215,10 @@ network_mrt_dump(struct mrt_rib *mr, str
time_t   now;
u_int16_ti, j;
 
+   /* can't announce more than one path so ignore add-path */
+   if (mr->add_path)
+   return;
+
now = time(NULL);
for (i = 0; i < mr->nentries; i++) {
mre = >entries[i];
@@ -1586,10 +1594,11 @@ show_mrt_notification(u_char *p, u_int16
 
 /* XXX this function does not handle JSON output */
 static void
-show_mrt_update(u_char *p, u_int16_t len, int reqflags)
+show_mrt_update(u_char *p, u_int16_t len, int reqflags, int addpath)
 {
struct bgpd_addr prefix;
int pos;
+   u_int32_t pathid;
u_int16_t wlen, alen;
u_int8_t prefixlen;
 
@@ -1609,12 +1618,25 @@ show_mrt_update(u_char *p, u_int16_t len
if (wlen > 0) {
printf("\n Withdrawn prefixes:");
while (wlen > 0) {
+   if (addpath) {
+   if (wlen <= sizeof(pathid)) {
+   printf("bad withdraw prefix");
+   return;
+   }
+   memcpy(, p, sizeof(pathid));
+   pathid = ntohl(pathid);
+   p += sizeof(pathid);
+   len -= sizeof(pathid);
+   wlen -= sizeof(pathid);
+   }
if ((pos = nlri_get_prefix(p, wlen, ,
)) == -1) {
printf("bad withdraw prefix");
return;
}
printf(" %s/%u", log_addr(), prefixlen);
+   if (addpath)
+   printf(" path-id %u", pathid);
p += pos;
len -= pos;
wlen -= pos;
@@ -1655,7 +1677,7 @@ show_mrt_update(u_char *p, u_int16_t len
attrlen += 1 + 2;
}
 
-   output->attr(p, attrlen, reqflags);
+   output->attr(p, attrlen, reqflags, addpath);
p += attrlen;
alen -= attrlen;
len -= attrlen;
@@ -1664,12 +1686,24 @@ show_mrt_update(u_char *p, u_int16_t len
if (len > 0) {
printf("NLRI prefixes:");
while (len > 0) {
+   if (addpath) {
+ 

rsync getopt_long cleanup

2021-07-13 Thread Claudio Jeker
I never really liked the getopt_long definitions in rsync. Too much magic
and chaos.

This moves the table out of main to gain some more space and to make it a
proper read-only object. Because of this struct opts also needs to become
a global but that is OK.

Clean up the required_argument options that have no short from. Instead of
small numbers use some defines and make the values larger than any char
value (I chose 1000 and up).

Fix --no-motd, it is just a flag setting a value. So just use the
getopt_long() method for doing that.

Sort the options alphabetically with the exception of no-XYZ options which
I added below the XYZ option itself.

IMO the result is better than what was there before.
-- 
:wq Claudio

Index: main.c
===
RCS file: /cvs/src/usr.bin/rsync/main.c,v
retrieving revision 1.55
diff -u -p -r1.55 main.c
--- main.c  30 Jun 2021 13:10:04 -  1.55
+++ main.c  13 Jul 2021 17:54:13 -
@@ -269,61 +269,67 @@ fargs_parse(size_t argc, char *argv[], s
return f;
 }
 
+static struct opts  opts;
+
+#define OP_ADDRESS 1000
+#define OP_PORT1001
+#define OP_RSYNCPATH   1002
+#define OP_TIMEOUT 1003
+#define OP_VERSION 1004
+
+const struct option lopts[] = {
+{ "address",   required_argument, NULL,OP_ADDRESS },
+{ "archive",   no_argument,NULL,   'a' },
+{ "compress",  no_argument,NULL,   'z' },
+{ "del",   no_argument,,  1 },
+{ "delete",no_argument,,  1 },
+{ "devices",   no_argument,,  1 },
+{ "no-devices",no_argument,,  0 },
+{ "dry-run",   no_argument,_run,  1 },
+{ "group", no_argument,_gids,1 },
+{ "no-group",  no_argument,_gids,0 },
+{ "help",  no_argument,NULL,   'h' },
+{ "links", no_argument,_links,   1 },
+{ "no-links",  no_argument,_links,   0 },
+{ "no-motd",   no_argument,_motd,  1 },
+{ "numeric-ids",   no_argument,_ids,  1 },
+{ "owner", no_argument,_uids,1 },
+{ "no-owner",  no_argument,_uids,0 },
+{ "perms", no_argument,_perms,   1 },
+{ "no-perms",  no_argument,_perms,   0 },
+{ "port",  required_argument, NULL,OP_PORT },
+{ "recursive", no_argument,,1 },
+{ "no-recursive",  no_argument,,0 },
+{ "rsh",   required_argument, NULL,'e' },
+{ "rsync-path",required_argument, NULL,OP_RSYNCPATH },
+{ "sender",no_argument,,   1 },
+{ "server",no_argument,,   1 },
+{ "specials",  no_argument,, 1 },
+{ "no-specials",   no_argument,, 0 },
+{ "timeout",   required_argument, NULL,OP_TIMEOUT },
+{ "times", no_argument,_times,   1 },
+{ "no-times",  no_argument,_times,   0 },
+{ "verbose",   no_argument,,   1 },
+{ "no-verbose",no_argument,,   0 },
+{ "version",   no_argument,NULL,   OP_VERSION },
+{ NULL,0,  NULL,   0 }
+};
+
 int
 main(int argc, char *argv[])
 {
-   struct opts  opts;
pid_tchild;
int  fds[2], sd = -1, rc, c, st, i;
struct sess   sess;
struct fargs*fargs;
char**args;
const char  *errstr;
-   const struct option  lopts[] = {
-   { "port",   required_argument, NULL,3 },
-   { "rsh",required_argument, NULL,'e' },
-   { "rsync-path", required_argument, NULL,1 },
-   { "sender", no_argument,,   1 },
-   { "server", no_argument,,   1 },
-   { "dry-run",no_argument,_run,  1 },
-   { "version",no_argument,NULL,   2 },
-   { "archive",no_argument,NULL,   'a' },
-   { "help",   no_argument,NULL,   'h' },
-   { "compress",   no_argument,NULL,   'z' },
-   { "del",no_argument,,  1 },
-   { "delete", no_argument,,  1 },
-   { "devices",no_argument,,  1 },
-   { "no-devices", no_argument,,  0 },
-   { "group",  no_argument,_gids,1 },
-   { "no-group",   no_argument,_gids,0 },
-   { "links",  

Re: bgpd refactor struct prefix

2021-07-14 Thread Claudio Jeker
On Tue, Jun 29, 2021 at 12:00:24PM +0200, Claudio Jeker wrote:
> This diff moves the rib_entry pointer re into the union to safe some
> space. For add-path I need to add a few more u_int32_t and that would
> blow the size of struct prefix from 128 to 132 bytes. malloc would round
> that up to 256bytes and that is bad for the struct that is allocted in
> millions in bgpd.
> 
> To make this somewhat save introduce PREFIX_FLAG_ADJOUT to mark prefixes
> that live in the adj-rib-out. Those prefixes can not access the re pointer
> also use a wrapper prefix_re() which returns the re pointer or NULL.
> Also add some assertions to make sure that prefixes don't end up in the
> wrong tree.
> 
> This change shrinks the struct back to 120bytes and gives me the space
> needed for add-path.
> 
> Please test

Ping

-- 
:wq Claudio

Index: rde.c
===
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.530
diff -u -p -r1.530 rde.c
--- rde.c   25 Jun 2021 09:25:48 -  1.530
+++ rde.c   29 Jun 2021 08:28:33 -
@@ -2298,6 +2298,7 @@ rde_dump_rib_as(struct prefix *p, struct
struct ibuf *wbuf;
struct attr *a;
struct nexthop  *nexthop;
+   struct rib_entry*re;
void*bp;
time_t   staletime;
size_t   aslen;
@@ -2330,7 +2331,8 @@ rde_dump_rib_as(struct prefix *p, struct
rib.origin = asp->origin;
rib.validation_state = p->validation_state;
rib.flags = 0;
-   if (p->re != NULL && p->re->active == p)
+   re = prefix_re(p);
+   if (re != NULL && re->active == p)
rib.flags |= F_PREF_ACTIVE;
if (!prefix_peer(p)->conf.ebgp)
rib.flags |= F_PREF_INTERNAL;
@@ -2412,14 +2414,16 @@ static void
 rde_dump_filter(struct prefix *p, struct ctl_show_rib_request *req)
 {
struct rde_aspath   *asp;
+   struct rib_entry*re;
 
if (!rde_match_peer(prefix_peer(p), >neighbor))
return;
 
asp = prefix_aspath(p);
+   re = prefix_re(p);
if (asp == NULL)/* skip pending withdraw in Adj-RIB-Out */
return;
-   if ((req->flags & F_CTL_ACTIVE) && p->re->active != p)
+   if ((req->flags & F_CTL_ACTIVE) && re != NULL && re->active != p)
return;
if ((req->flags & F_CTL_INVALID) &&
(asp->flags & F_ATTR_PARSE_ERR) == 0)
Index: rde.h
===
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
retrieving revision 1.240
diff -u -p -r1.240 rde.h
--- rde.h   17 Jun 2021 16:05:26 -  1.240
+++ rde.h   29 Jun 2021 08:33:18 -
@@ -56,10 +56,10 @@ struct rib {
struct filter_head  *in_rules_tmp;
u_int   rtableid;
u_int   rtableid_tmp;
+   enum reconf_action  state, fibstate;
+   u_int16_t   id;
u_int16_t   flags;
u_int16_t   flags_tmp;
-   u_int16_t   id;
-   enum reconf_action  state, fibstate;
 };
 
 #define RIB_ADJ_IN 0
@@ -317,13 +317,13 @@ struct prefix {
union {
struct {
LIST_ENTRY(prefix)   rib, nexthop;
+   struct rib_entry*re;
} list;
struct {
RB_ENTRY(prefix) index, update;
} tree;
}entry;
struct pt_entry *pt;
-   struct rib_entry*re;
struct rde_aspath   *aspath;
struct rde_community*communities;
struct rde_peer *peer;
@@ -338,6 +338,7 @@ struct prefix {
 #definePREFIX_FLAG_DEAD0x04/* locked but removed */
 #definePREFIX_FLAG_STALE   0x08/* stale entry (graceful 
reload) */
 #definePREFIX_FLAG_MASK0x0f/* mask for the prefix types */
+#definePREFIX_FLAG_ADJOUT  0x10/* prefix is in the adj-out rib 
*/
 #definePREFIX_NEXTHOP_LINKED   0x40/* prefix is linked onto 
nexthop list */
 #definePREFIX_FLAG_LOCKED  0x80/* locked by rib walker */
 };
@@ -637,6 +638,14 @@ static inline u_int8_t
 prefix_vstate(struct prefix *p)
 {
return (p->validation_state & ROA_MASK);
+}
+
+static inline struct rib_entry *
+prefix_re(struct prefix *p)
+{
+   if (p->flags & PREFIX_FLAG_ADJOUT)
+   return NULL;
+   return (p->entry.list.re);
 }
 
 voidnexthop_init(u_int32_t);
Index: rde_rib.c
===

Re: Do not spin on the NET_LOCK() in kqueue

2021-07-29 Thread Claudio Jeker
On Thu, Jul 29, 2021 at 09:51:43AM +0200, Martin Pieuchot wrote:
> On 26/07/21(Mon) 09:23, Martin Pieuchot wrote:
> > On 26/07/21(Mon) 08:55, Martin Pieuchot wrote:
> > > On 21/07/21(Wed) 10:18, Martin Pieuchot wrote:
> > > > On 11/07/21(Sun) 14:45, Visa Hankala wrote:
> > > > > On Sat, Jul 10, 2021 at 05:26:57PM +0200, Martin Pieuchot wrote:
> > > > > > One of the reasons for the drop of performances in the kqueue-based
> > > > > > poll/select is the fact that kqueue filters are called up to 3 times
> > > > > > per syscall and that they all spin on the NET_LOCK() for TCP/UDP
> > > > > > packets.
> > > > > > 
> > > > > > Diff below is a RFC for improving the situation.
> > > > > > 
> > > > > > socket kqueue filters mainly check for the amount of available 
> > > > > > items to
> > > > > > read/write.  This involves comparing various socket buffer fields 
> > > > > > (sb_cc,
> > > > > > sb_lowat, etc).  The diff below introduces a new mutex to serialize
> > > > > > updates of those fields with reads in the kqueue filters.
> > > > > > 
> > > > > > Since these fields are always modified with the socket lock held, 
> > > > > > either
> > > > > > the mutex or the solock are enough to have a coherent view of them.
> > > > > > Note that either of these locks is necessary only if multiple fields
> > > > > > have to be read (like in sbspace()).
> > > > > > 
> > > > > > Other per-socket fields accessed in the kqueue filters are never
> > > > > > combined (with &&) to determine a condition.  So assuming it is 
> > > > > > fine to
> > > > > > read register-sized fields w/o the socket lock we can safely remove 
> > > > > > it
> > > > > > there.
> > > > > > 
> > > > > > Could such mutex also be used to serialize klist updates?
> > > > > 
> > > > > I think the lock should be such that it can serialize socket klists.
> > > > > 
> > > > > As the main motivator for this change is kqueue, the viability of 
> > > > > using
> > > > > the mutex for the klist locking should be checked now. The mutex has 
> > > > > to
> > > > > be held whenever calling KNOTE() on sb_sel.si_note, or selwakeup() on
> > > > > sb_sel. Then the socket f_event callbacks will not need to lock the
> > > > > mutex themselves.
> > > > > 
> > > > > I had a diff that serialized socket klists using solock(). It did not
> > > > > work well because it increased lock contention, especially when using
> > > > > kqueue as backend for poll(2) and select(2). The diff is not even
> > > > > correct any longer since recent changes to socket locking have
> > > > > introduced new lock order constraints that conflict with it.
> > > > 
> > > > Updated diff below does that.  It also uses a single per-socket mutex as
> > > > suggested by bluhm@.
> > > > 
> > > > Note that as long poll(2) & select(2) use the current implementation a
> > > > KERNEL_LOCK()/UNLOCK() dance is necessary in sowakeup().  The goal of
> > > > this change combined with the poll/select rewrite is to get rid of this
> > > > dance.
> > > 
> > > Updated diff after recent commits, more comments?  Oks?
> > 
> > Previous diff had a double mtx_enter() in filt_fifowrite_common(), this
> > one use the *locked() version of sbspace() to prevent it.
> 
> New diff fixing a locking dance pointed out by visa@.

I think the diff is fine. It does show a few places that should be
improved on. e.g. some of those macros in socketvar.h should be
implemented as functions or inline functions or the fact that high level
code (e.g. TCP) is directly manipulating socket buffer internals.

I'm not a big fan of either-this-lock-or-that-lock locking schemes. They
are just confusing. I guess in the long run the mutex should be used all
the time.

Maybe it is best to commit it and look for any fallout.

> Index: kern/uipc_socket.c
> ===
> RCS file: /cvs/src/sys/kern/uipc_socket.c,v
> retrieving revision 1.264
> diff -u -p -r1.264 uipc_socket.c
> --- kern/uipc_socket.c26 Jul 2021 05:51:13 -  1.264
> +++ kern/uipc_socket.c29 Jul 2021 07:31:32 -
> @@ -84,7 +84,7 @@ int filt_solistenprocess(struct knote *k
>  int  filt_solisten_common(struct knote *kn, struct socket *so);
>  
>  const struct filterops solisten_filtops = {
> - .f_flags= FILTEROP_ISFD,
> + .f_flags= FILTEROP_ISFD | FILTEROP_MPSAFE,
>   .f_attach   = NULL,
>   .f_detach   = filt_sordetach,
>   .f_event= filt_solisten,
> @@ -93,7 +93,7 @@ const struct filterops solisten_filtops 
>  };
>  
>  const struct filterops soread_filtops = {
> - .f_flags= FILTEROP_ISFD,
> + .f_flags= FILTEROP_ISFD | FILTEROP_MPSAFE,
>   .f_attach   = NULL,
>   .f_detach   = filt_sordetach,
>   .f_event= filt_soread,
> @@ -102,7 +102,7 @@ const struct filterops soread_filtops = 
>  };
>  
>  const struct filterops sowrite_filtops = {
> - .f_flags= FILTEROP_ISFD,
> + .f_flags= 

Re: bgpd add add-path receive support

2021-08-09 Thread Claudio Jeker
On Fri, Aug 06, 2021 at 08:34:18PM +0200, Sebastian Benoit wrote:
> Claudio Jeker(cje...@diehard.n-r-g.com) on 2021.08.04 17:55:45 +0200:
> > On Fri, Jul 30, 2021 at 12:02:12PM +0200, Claudio Jeker wrote:
> > > This diff implements the bit to support the receive side of
> > > RFC7911 - Advertisement of Multiple Paths in BGP.
> > > 
> > > I did some basic tests and it works for me. People running route
> > > collectors should give this a try. The interaction of Add-Path and bgpctl
> > > probably needs some work. Also the MRT dumper needs to be updated to
> > > support RFC8050. I have a partial diff for that ready as well.
> > > 
> > > Sending out multiple paths will follow in a later step since that is a
> > > bit more complex. I still need to decide how stable I want to make the
> > > assigned path_ids for the multiple paths and then changes to the decision
> > > process and adjrib-out are required to allow multipe paths there.
> > 
> > Updated diff that includes some minimal support for bgpctl.
> > This add 'bgpctl show rib nei foo path-id 42' as a way to limit which
> > paths to show. Now the RFC itself is very flexible in how path-ids are
> > assigned (it is possible that different prefixes have different path-ids)
> > but the assumtion is that most systems assign path-id in a stable way and
> > so it makes sense to allow to filter on path-id.
> > Apart from that not much changed.
> 
> ok benno@

Thanks a lot :)
 
> Only one thing, I worry that using this while the sending side is not working 
> can lead to
> blackholing of prefixes.
> 

Add-path allows for send / recv to be independent and so this is would me
more of a common issue with add-path. In general having more paths to
select from should help to stop oscilation (e.g. with route reflectors)
but I think this is frequently used to collect routes and still get full
views. Not sure if blackholing is possible (in the end there are more
routes to select from available) but route loops could be an issue.

By default add-path is disabled and that will remain. I agree that
operators need to evaluate carefully what add-path will give them.

Also plan is to finish the MRT support for add-path and then work on
add-path send. So this should arrive soon as well :)

-- 
:wq Claudio

> > 
> > -- 
> > :wq Claudio
> > 
> > Index: bgpctl/bgpctl.8
> > ===
> > RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.8,v
> > retrieving revision 1.99
> > diff -u -p -r1.99 bgpctl.8
> > --- bgpctl/bgpctl.8 16 Jun 2021 16:24:12 -  1.99
> > +++ bgpctl/bgpctl.8 4 Aug 2021 13:15:53 -
> > @@ -348,6 +348,13 @@ Show RIB memory statistics.
> >  Show only entries from the specified peer.
> >  .It Cm neighbor group Ar description
> >  Show only entries from the specified peer group.
> > +.It Cm path-id Ar pathid
> > +Show only entries which match the specified
> > +.Ar pathid .
> > +Must be used together with either
> > +.Cm neighbor
> > +or
> > +.Cm out .
> >  .It Cm peer-as Ar as
> >  Show all entries with
> >  .Ar as
> > Index: bgpctl/bgpctl.c
> > ===
> > RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
> > retrieving revision 1.272
> > diff -u -p -r1.272 bgpctl.c
> > --- bgpctl/bgpctl.c 2 Aug 2021 16:51:39 -   1.272
> > +++ bgpctl/bgpctl.c 4 Aug 2021 15:54:25 -
> > @@ -249,6 +249,7 @@ main(int argc, char *argv[])
> > ribreq.neighbor = neighbor;
> > strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
> > ribreq.aid = res->aid;
> > +   ribreq.path_id = res->pathid;
> > ribreq.flags = res->flags;
> > imsg_compose(ibuf, type, 0, 0, -1, , sizeof(ribreq));
> > break;
> > Index: bgpctl/parser.c
> > ===
> > RCS file: /cvs/src/usr.sbin/bgpctl/parser.c,v
> > retrieving revision 1.106
> > diff -u -p -r1.106 parser.c
> > --- bgpctl/parser.c 16 Feb 2021 08:30:21 -  1.106
> > +++ bgpctl/parser.c 4 Aug 2021 13:08:31 -
> > @@ -61,7 +61,8 @@ enum token_type {
> > RD,
> > FAMILY,
> > RTABLE,
> > -   FILENAME
> > +   FILENAME,
> > +   PATHID,
> >  };
> >  
> >  struct token {
> > @@ -114,6 +115,7 @@ static const struct token t_log[];
> >  static const struct token t_fib_table[];
> >  static const struct token t_show_fib_table[];
> >  stat

bgpd MRT RFC8050 support (add-path for mrt dumps)

2021-08-09 Thread Claudio Jeker
This diff adds the bits needed to support add-path in MRT dumps.
The problem here is that MRT as a stateless protocol has no chance
to know what kind of encoding (add-path or not) is used for the NLRI in
message dumps. And for table dumps there is a need to add an extra field
to the dumps to show the path-id.

There are two issues:
- for message dumps: it is necessary to peek into UPDATE messages to
  figure out if that update is using add-path or not. This comes from the
  fact that the add-path RFC allows to set the option per AFI/SAFI and
  also per direction. This is a major pain in bgpd since UPDATE messages
  are actually parsed in the RDE and not in the SE. The SE just does the
  basic lenght checks (header size, total length). So this peak into the
  packet needs to be done with some care (especialy for MP encoded
  UPDATEs).

- for table dumps the RFC did a major fobar and defined a extra special
  encoding for non-IPv4/IPv6 prefixes. In the general encoding the path-id
  is not part of the rib entries sub-struct but is instead part of the
  NLRI. This encoding is to complex to build into the bgpd codebase and it
  seems the only other BGP implementation supporting RIB_GENERIC_ADDPATH,
  gobgp, is also not implementing it according to the RFC but instead is
  using the same encoding as for the other _ADDPATH types. OpenBGPD will
  do the same.

This seems to work for me and results in the right output in bgpctl.

Please review mrt_bgp_guess_aid() and check if all checks are correct to
ensure we don't run off the rails.
-- 
:wq Claudio

Index: mrt.c
===
RCS file: /cvs/src/usr.sbin/bgpd/mrt.c,v
retrieving revision 1.104
diff -u -p -r1.104 mrt.c
--- mrt.c   24 Jun 2021 10:04:05 -  1.104
+++ mrt.c   9 Aug 2021 10:13:43 -
@@ -91,23 +91,128 @@ int mrt_open(struct mrt *, time_t);
x == MRT_TABLE_DUMP_V2) ? RDEIDX : SEIDX\
)
 
-void
-mrt_dump_bgp_msg(struct mrt *mrt, void *pkg, u_int16_t pkglen,
-struct peer *peer)
+static u_int8_t
+mrt_bgp_guess_aid(u_int8_t *pkg, u_int16_t pkglen)
+{
+   u_int16_t wlen, alen, len, afi;
+   u_int8_t type, aid;
+
+   pkg += MSGSIZE_HEADER;
+   pkglen -= MSGSIZE_HEADER;
+
+   if (pkglen < 4)
+   goto bad;
+
+   memcpy(, pkg, 2);
+   wlen = ntohs(wlen);
+   pkg += 2;
+   pkglen -= 2;
+
+   memcpy(, pkg, 2);
+   alen = ntohs(alen);
+   pkg += 2;
+   pkglen -= 2;
+
+   if (wlen > 0 || alen < pkglen || (wlen == 0 && alen == 0)) {
+   /* UPDATE has withdraw or NLRI prefixes or IPv4 EoR */
+   return AID_INET;
+   }
+
+   /* bad attribute length */
+   if (alen > pkglen)
+   goto bad;
+
+   /* try to extract AFI/SAFI from the MP attributes */
+   while (alen > 0) {
+   if (alen < 3)
+   goto bad;
+   type = pkg[1];
+   if (pkg[0] & ATTR_EXTLEN) {
+   if (alen < 4)
+   goto bad;
+   memcpy(, pkg + 2, 2);
+   len = ntohs(len);
+   pkg += 4;
+   alen -= 4;
+   } else {
+   len = pkg[2];
+   pkg += 3;
+   alen -= 3;
+   }
+   if (len > alen)
+   goto bad;
+
+   if (type == ATTR_MP_REACH_NLRI ||
+   type == ATTR_MP_UNREACH_NLRI) {
+   if (alen < 3)
+   goto bad;
+   memcpy(, pkg, 2);
+   afi = ntohs(afi);
+   if (afi2aid(afi, pkg[2], ) == -1)
+   goto bad;
+   return aid;
+   }
+
+   pkg += len;
+   alen -= len;
+   }
+
+bad:
+   return AID_UNSPEC;
+}
+
+static u_int16_t
+mrt_bgp_msg_subtype(struct mrt *mrt, void *pkg, u_int16_t pkglen,
+struct peer *peer, enum msg_type msgtype, int in)
 {
-   struct ibuf *buf;
-   int  incoming = 0;
u_int16_tsubtype = BGP4MP_MESSAGE;
+   u_int8_t aid, mask;
 
if (peer->capa.neg.as4byte)
subtype = BGP4MP_MESSAGE_AS4;
 
+   if (msgtype != UPDATE)
+   return subtype;
+
+   /*
+* RFC8050 adjust types for add-path enabled sessions.
+* It is necessary to extract the AID from UPDATES to decide
+* if the add-path types are needed or not. The ADDPATH
+* subtypes only matter for BGP UPDATES.
+*/
+
+   mask = in ? CAPA_AP_RECV : CAPA_AP_SEND;
+   /* only guess if add-path could be active */
+   if (peer->capa.neg.add_path[0] & mask) {
+   aid = mrt_bgp_guess_aid(pkg, pkglen);
+   if (aid != AID_UNSPEC &&
+  

Re: libedit: stop ignoring SIGINT

2021-08-09 Thread Claudio Jeker
On Mon, Aug 09, 2021 at 01:19:08PM +0200, Ingo Schwarze wrote:
> Hi,
> 
> as mentioned earlier, deraadt@ reported that sftp(1) ignores Ctrl-C.
> Fixing that without longjmp(3) requires making editline(3) better
> behaved.
> 
> Currently, when read(2) from the terminal gets interrupted by a
> signal, editline(3) ignores the (first) signal and unconditionally
> calls read(2) a second time.  That seems wrong: if the user hits
> Ctrl-C, it is sane to assume that they meant it, not that they
> want it ignored.
> 
> The following patch causes el_gets(3) and el_wgets(3) to return
> failure when read(2)ing from the terminal is interrupted by a
> signal other than SIGCONT or SIGWINCH.  That allows the calling
> program to decide what to do, usually either exit the program or
> provide a fresh prompt to the user.
> 
> If i know how to grep(1), the following programs in the base system
> use -ledit:
> 
>  * bc(1)
>It behaves well with the patch: Ctrl-C discards the current
>input line and starts a new input line.
>The reason why this already works even without the patch
>is that bc(1) does very scary stuff inside the signal handler:
>pass a file-global EditLine pointer on the heap to el_line(3)
>and access fields inside the returned struct.  Needless to
>say that no signal handler should do such things...
> 
>  * cdio(1)
>Behaviour is acceptable and unchanged with the patch:
>Ctrl-C exits cdio(1).
> 
>  * ftp(1)
>It behaves well with the patch: Ctrl-C discards the current
>input line and provides a fresh prompt.
>The reason why it already works without the patch is that ftp(1)
>uses setjmp(3)/longjmp(3) to forcefully grab back control
>from el_gets(3) without waiting for it to return.
> 
>  * lldb(1)
>It misbehaves with or without the patch and ignores Ctrl-C.
>I freely admit that i don't feel too enthusiastic about
>debugging that beast.
> 
>  * sftp(1)
>Behaviour is improved with the patch: Ctrl-C now exits sftp(1).
>If desired, i can supply a very simple follow-up patch to sftp.c
>to instead behave like ftp(1) and bc(1), i.e. discard the
>current input line and provide a fresh prompt.
>Neither doing undue work in the signal handler nor longjmp(3)
>will be required for that (if this patch gets committed).
> 
>  * bgplgsh(8), fsdb(8)
>I have no idea how to test those.  Does anyone think that testing
>either of them would be required?

I had a quick test with bgplgsh(8), hitting Ctrl-C exits bgplgsh. Same
before with or without the diff. Not sure if anyone is actually using
bgplgsh(8) -- I never used it.

-- 
:wq Claudio



bgpd add add-path receive support

2021-07-30 Thread Claudio Jeker
This diff implements the bit to support the receive side of
RFC7911 - Advertisement of Multiple Paths in BGP.

I did some basic tests and it works for me. People running route
collectors should give this a try. The interaction of Add-Path and bgpctl
probably needs some work. Also the MRT dumper needs to be updated to
support RFC8050. I have a partial diff for that ready as well.

Sending out multiple paths will follow in a later step since that is a
bit more complex. I still need to decide how stable I want to make the
assigned path_ids for the multiple paths and then changes to the decision
process and adjrib-out are required to allow multipe paths there.

-- 
:wq Claudio

Index: parse.y
===
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
retrieving revision 1.417
diff -u -p -r1.417 parse.y
--- parse.y 17 Jun 2021 16:05:26 -  1.417
+++ parse.y 22 Jun 2021 10:48:50 -
@@ -204,7 +204,8 @@ typedef struct {
 %token GROUP NEIGHBOR NETWORK
 %token EBGP IBGP
 %token LOCALAS REMOTEAS DESCR LOCALADDR MULTIHOP PASSIVE MAXPREFIX RESTART
-%token ANNOUNCE CAPABILITIES REFRESH AS4BYTE CONNECTRETRY ENHANCED
+%token ANNOUNCE CAPABILITIES REFRESH AS4BYTE CONNECTRETRY ENHANCED ADDPATH
+%token SEND RECV
 %token DEMOTE ENFORCE NEIGHBORAS ASOVERRIDE REFLECTOR DEPEND DOWN
 %token DUMP IN OUT SOCKET RESTRICTED
 %token LOG TRANSPARENT
@@ -1455,6 +1456,16 @@ peeropts : REMOTEAS as4number{
| ANNOUNCE AS4BYTE yesno {
curpeer->conf.capabilities.as4byte = $3;
}
+   | ANNOUNCE ADDPATH RECV yesno {
+   int8_t *ap = curpeer->conf.capabilities.add_path;
+   u_int8_t i;
+
+   for (i = 0; i < AID_MAX; i++)
+   if ($4)
+   *ap++ |= CAPA_AP_RECV;
+   else
+   *ap++ &= ~CAPA_AP_RECV;
+   }
| EXPORT NONE {
curpeer->conf.export_type = EXPORT_NONE;
}
@@ -2878,6 +2889,7 @@ lookup(char *s)
{ "AS", AS},
{ "IPv4",   IPV4},
{ "IPv6",   IPV6},
+   { "add-path",   ADDPATH},
{ "ah", AH},
{ "allow",  ALLOW},
{ "announce",   ANNOUNCE},
@@ -2965,6 +2977,7 @@ lookup(char *s)
{ "quick",  QUICK},
{ "rd", RD},
{ "rde",RDE},
+   { "recv",   RECV},
{ "refresh",REFRESH },
{ "reject", REJECT},
{ "remote-as",  REMOTEAS},
@@ -2978,6 +2991,7 @@ lookup(char *s)
{ "rtlabel",RTLABEL},
{ "rtr",RTR},
{ "self",   SELF},
+   { "send",   SEND},
{ "set",SET},
{ "socket", SOCKET },
{ "source-as",  SOURCEAS},
Index: rde.c
===
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
retrieving revision 1.531
diff -u -p -r1.531 rde.c
--- rde.c   27 Jul 2021 07:50:01 -  1.531
+++ rde.c   30 Jul 2021 09:16:53 -
@@ -50,10 +50,10 @@ void rde_dispatch_imsg_parent(struct i
 voidrde_dispatch_imsg_rtr(struct imsgbuf *);
 voidrde_dispatch_imsg_peer(struct rde_peer *, void *);
 voidrde_update_dispatch(struct rde_peer *, struct imsg *);
-int rde_update_update(struct rde_peer *, struct filterstate *,
+int rde_update_update(struct rde_peer *, u_int32_t,
+ struct filterstate *, struct bgpd_addr *, u_int8_t);
+voidrde_update_withdraw(struct rde_peer *, u_int32_t,
 struct bgpd_addr *, u_int8_t);
-voidrde_update_withdraw(struct rde_peer *, struct bgpd_addr *,
-u_int8_t);
 int rde_attr_parse(u_char *, u_int16_t, struct rde_peer *,
 struct filterstate *, struct mpattr *);
 int rde_attr_add(struct filterstate *, u_char *, u_int16_t);
@@ -1183,7 +1183,7 @@ rde_update_dispatch(struct rde_peer *pee
u_int16_tattrpath_len;
u_int16_tnlri_len;
u_int8_t aid, prefixlen, safi, subtype;
-   u_int32_tfas;
+   u_int32_tfas, pathid;
 
p = imsg->data;
 
@@ -1288,6 +1288,21 @@ rde_update_dispatch(struct rde_peer *pee
goto done;
}
 
+   if (peer_has_add_path(peer, AID_INET, CAPA_AP_RECV)) {
+  

Re: rpki-client support more http status codes

2021-08-04 Thread Claudio Jeker
On Wed, Aug 04, 2021 at 10:53:39AM +0200, Claudio Jeker wrote:
> This adds a few more HTTP Status codes to the mix of the accepted ones.
> Mainly 100, 103 and 203 are now also accepted. All other codes in the 1xx
> and 2xx are still considered an error since they are not expected from the
> GET request made by the http client. This is a minimal HTTP client and it
> should remain minimal. If a server is sending back something unexpected
> just fail and fall back to rsync.


Update with additional comments for the various status codes.

-- 
:wq Claudio

Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.34
diff -u -p -r1.34 http.c
--- http.c  23 Jul 2021 16:03:47 -  1.34
+++ http.c  4 Aug 2021 15:22:22 -
@@ -865,7 +865,9 @@ http_request(struct http_connection *con
 
 /*
  * Parse the HTTP status line.
- * Return 0 for status codes 200, 301-304, 307-308.
+ * Return 0 for status codes 100, 103, 200, 203, 301-304, 307-308.
+ * The other 1xx and 2xx status codes are explicitly not handled and are
+ * considered an error.
  * Failure codes and other errors return -1.
  * The redirect loop limit is enforced here.
  */
@@ -885,7 +887,7 @@ http_parse_status(struct http_connection
cp++;
 
strlcpy(ststr, cp, sizeof(ststr));
-   status = strtonum(ststr, 200, 599, );
+   status = strtonum(ststr, 100, 599, );
if (errstr != NULL) {
strnvis(gerror, cp, sizeof gerror, VIS_SAFE);
warnx("Error retrieving %s: %s", http_info(conn->host),
@@ -894,19 +896,23 @@ http_parse_status(struct http_connection
}
 
switch (status) {
-   case 301:
-   case 302:
-   case 303:
-   case 307:
-   case 308:
+   case 301:   /* Redirect: moved permanently */
+   case 302:   /* Redirect: found / moved temporarily */
+   case 303:   /* Redirect: see other */
+   case 307:   /* Redirect: temporary redirect */
+   case 308:   /* Redirect: permanent redirect */
if (conn->req->redirect_loop++ > 10) {
warnx("%s: Too many redirections requested",
http_info(conn->host));
return -1;
}
/* FALLTHROUGH */
-   case 200:
-   case 304:
+   case 100:   /* Informational: continue (ignored) */
+   case 103:   /* Informational: early hints (ignored) */
+   /* FALLTHROUGH */
+   case 200:   /* Success: OK */
+   case 203:   /* Success: non-authoritative information (proxy) */
+   case 304:   /* Redirect: not modified */
conn->status = status;
break;
default:
@@ -931,6 +937,14 @@ http_isredirect(struct http_connection *
return 0;
 }
 
+static inline int
+http_isok(struct http_connection *conn)
+{
+   if (conn->status >= 200 && conn->status < 300)
+   return 1;
+   return 0;
+}
+
 static void
 http_redirect(struct http_connection *conn)
 {
@@ -1165,7 +1179,7 @@ again:
}
 
/* Check status header and decide what to do next */
-   if (conn->status == 200 || http_isredirect(conn)) {
+   if (http_isok(conn) || http_isredirect(conn)) {
if (http_isredirect(conn))
http_redirect(conn);
 
@@ -1174,6 +1188,8 @@ again:
else
conn->state = STATE_RESPONSE_DATA;
goto again;
+   } else if (conn->status == 100 || conn->status == 103) {
+   conn->state = STATE_RESPONSE_STATUS;
} else if (conn->status == 304) {
return http_done(conn, HTTP_NOT_MOD);
}



Re: bgpd add add-path receive support

2021-08-04 Thread Claudio Jeker
On Fri, Jul 30, 2021 at 12:02:12PM +0200, Claudio Jeker wrote:
> This diff implements the bit to support the receive side of
> RFC7911 - Advertisement of Multiple Paths in BGP.
> 
> I did some basic tests and it works for me. People running route
> collectors should give this a try. The interaction of Add-Path and bgpctl
> probably needs some work. Also the MRT dumper needs to be updated to
> support RFC8050. I have a partial diff for that ready as well.
> 
> Sending out multiple paths will follow in a later step since that is a
> bit more complex. I still need to decide how stable I want to make the
> assigned path_ids for the multiple paths and then changes to the decision
> process and adjrib-out are required to allow multipe paths there.

Updated diff that includes some minimal support for bgpctl.
This add 'bgpctl show rib nei foo path-id 42' as a way to limit which
paths to show. Now the RFC itself is very flexible in how path-ids are
assigned (it is possible that different prefixes have different path-ids)
but the assumtion is that most systems assign path-id in a stable way and
so it makes sense to allow to filter on path-id.
Apart from that not much changed.

-- 
:wq Claudio

Index: bgpctl/bgpctl.8
===
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.8,v
retrieving revision 1.99
diff -u -p -r1.99 bgpctl.8
--- bgpctl/bgpctl.8 16 Jun 2021 16:24:12 -  1.99
+++ bgpctl/bgpctl.8 4 Aug 2021 13:15:53 -
@@ -348,6 +348,13 @@ Show RIB memory statistics.
 Show only entries from the specified peer.
 .It Cm neighbor group Ar description
 Show only entries from the specified peer group.
+.It Cm path-id Ar pathid
+Show only entries which match the specified
+.Ar pathid .
+Must be used together with either
+.Cm neighbor
+or
+.Cm out .
 .It Cm peer-as Ar as
 Show all entries with
 .Ar as
Index: bgpctl/bgpctl.c
===
RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v
retrieving revision 1.272
diff -u -p -r1.272 bgpctl.c
--- bgpctl/bgpctl.c 2 Aug 2021 16:51:39 -   1.272
+++ bgpctl/bgpctl.c 4 Aug 2021 15:54:25 -
@@ -249,6 +249,7 @@ main(int argc, char *argv[])
ribreq.neighbor = neighbor;
strlcpy(ribreq.rib, res->rib, sizeof(ribreq.rib));
ribreq.aid = res->aid;
+   ribreq.path_id = res->pathid;
ribreq.flags = res->flags;
imsg_compose(ibuf, type, 0, 0, -1, , sizeof(ribreq));
break;
Index: bgpctl/parser.c
===
RCS file: /cvs/src/usr.sbin/bgpctl/parser.c,v
retrieving revision 1.106
diff -u -p -r1.106 parser.c
--- bgpctl/parser.c 16 Feb 2021 08:30:21 -  1.106
+++ bgpctl/parser.c 4 Aug 2021 13:08:31 -
@@ -61,7 +61,8 @@ enum token_type {
RD,
FAMILY,
RTABLE,
-   FILENAME
+   FILENAME,
+   PATHID,
 };
 
 struct token {
@@ -114,6 +115,7 @@ static const struct token t_log[];
 static const struct token t_fib_table[];
 static const struct token t_show_fib_table[];
 static const struct token t_communication[];
+static const struct token t_show_rib_path[];
 
 static const struct token t_main[] = {
{ KEYWORD,  "reload",   RELOAD, t_communication},
@@ -178,10 +180,11 @@ static const struct token t_show_rib[] =
{ FLAG, "in",   F_CTL_ADJ_IN,   t_show_rib},
{ FLAG, "out",  F_CTL_ADJ_OUT,  t_show_rib},
{ KEYWORD,  "neighbor", NONE,   t_show_rib_neigh},
+   { KEYWORD,  "ovs",  NONE,   t_show_ovs},
+   { KEYWORD,  "path-id",  NONE,   t_show_rib_path},
{ KEYWORD,  "table",NONE,   t_show_rib_rib},
{ KEYWORD,  "summary",  SHOW_SUMMARY,   t_show_summary},
{ KEYWORD,  "memory",   SHOW_RIB_MEM,   NULL},
-   { KEYWORD,  "ovs",  NONE,   t_show_ovs},
{ FAMILY,   "", NONE,   t_show_rib},
{ PREFIX,   "", NONE,   t_show_prefix},
{ ENDTOKEN, "", NONE,   NULL}
@@ -479,6 +482,11 @@ static const struct token t_show_fib_tab
{ ENDTOKEN, "", NONE,   NULL}
 };
 
+static const struct token t_show_rib_path[] = {
+   { PATHID,   "", NONE,   t_show_rib},
+   { ENDTOKEN, "", NONE,   NULL}
+};
+
 static struct parse_result res;
 
 const struct token *match_token(int *argc, char **argv[],
@@ -748,6 +756,7 @@ match_token(int *argc, char **argv[], co
case PREPSELF:

rpki-client support more http status codes

2021-08-04 Thread Claudio Jeker
This adds a few more HTTP Status codes to the mix of the accepted ones.
Mainly 100, 103 and 203 are now also accepted. All other codes in the 1xx
and 2xx are still considered an error since they are not expected from the
GET request made by the http client. This is a minimal HTTP client and it
should remain minimal. If a server is sending back something unexpected
just fail and fall back to rsync.

OK?
-- 
:wq Claudio

Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.34
diff -u -p -r1.34 http.c
--- http.c  23 Jul 2021 16:03:47 -  1.34
+++ http.c  4 Aug 2021 08:48:01 -
@@ -865,7 +865,9 @@ http_request(struct http_connection *con
 
 /*
  * Parse the HTTP status line.
- * Return 0 for status codes 200, 301-304, 307-308.
+ * Return 0 for status codes 100, 103, 200, 203, 301-304, 307-308.
+ * The other 1xx and 2xx status codes are explicitly not handled and are
+ * considered an error.
  * Failure codes and other errors return -1.
  * The redirect loop limit is enforced here.
  */
@@ -885,7 +887,7 @@ http_parse_status(struct http_connection
cp++;
 
strlcpy(ststr, cp, sizeof(ststr));
-   status = strtonum(ststr, 200, 599, );
+   status = strtonum(ststr, 100, 599, );
if (errstr != NULL) {
strnvis(gerror, cp, sizeof gerror, VIS_SAFE);
warnx("Error retrieving %s: %s", http_info(conn->host),
@@ -905,7 +907,11 @@ http_parse_status(struct http_connection
return -1;
}
/* FALLTHROUGH */
+   case 100:
+   case 103:
+   /* FALLTHROUGH */
case 200:
+   case 203:
case 304:
conn->status = status;
break;
@@ -931,6 +937,14 @@ http_isredirect(struct http_connection *
return 0;
 }
 
+static inline int
+http_isok(struct http_connection *conn)
+{
+   if (conn->status >= 200 && conn->status < 300)
+   return 1;
+   return 0;
+}
+
 static void
 http_redirect(struct http_connection *conn)
 {
@@ -1165,7 +1179,7 @@ again:
}
 
/* Check status header and decide what to do next */
-   if (conn->status == 200 || http_isredirect(conn)) {
+   if (http_isok(conn) || http_isredirect(conn)) {
if (http_isredirect(conn))
http_redirect(conn);
 
@@ -1174,6 +1188,8 @@ again:
else
conn->state = STATE_RESPONSE_DATA;
goto again;
+   } else if (conn->status == 100 || conn->status == 103) {
+   conn->state = STATE_RESPONSE_STATUS;
} else if (conn->status == 304) {
return http_done(conn, HTTP_NOT_MOD);
}



OpenBGPD 7.2 released

2021-09-23 Thread Claudio Jeker
We have released OpenBGPD 7.2, which will be arriving in the
OpenBGPD directory of your local OpenBSD mirror soon.

This release includes the following changes to the previous release:

* Support for RFC 9072 - Extended Optional Parameters Lenght for
  BGP OPEN Message

* Support for RFC 8050 - MRT Format with BGP Additional Path Extensions

* Implement receive side of RFC 7911 - Advertisement of Multiple Paths
  in BGP. OpenBGPD is currently not able to send multiple paths out.

* Improve checks of VRPs loaded via RTR or from the roa-set table.

* Allow to optionally specify an expiry time for roa-set entries to
  mitigate BGP route decision making based on outdated RPKI data.
  OpenBGPD's companion rpki-client(8) produces roa-sets with the
  new 'expires' property

OpenBGPD-portable is known to compile and run on FreeBSD, and
the Linux distributions Alpine, Debian, Fedora, RHEL/CentOS and Ubuntu.
It is our hope that packagers take interest and help adapt OpenBGPD-portable
to more distributions.

We welcome feedback and improvements from the broader community.
Thanks to all of the contributors who helped make this release
possible.



Re: retire hifn safe ubsec

2021-10-21 Thread Claudio Jeker
On Thu, Oct 21, 2021 at 04:30:02PM +0200, Alexander Bluhm wrote:
> Hi,
> 
> Goal is to retire the async crypto API.  It is slow and adds
> complexity which hinders MP progress in IPsec.  It is used by the
> old PCI devices hifn(4), safe(4), and ubsec(4).
> 
> These devices are not common anymore.  Using the CPU for crypto is
> faster than offloading via the PCI bus.  By having special requirements
> for the crypto API, those devices slow down modern machines.  They
> only support crypto algorithms that are insecure nowadays.
> 
> ok to remove hifn(4) safe(4) ubsec(4) ?
> 

Agreed, I see little benefit in having them around now.

-- 
:wq Claudio



Re: sigwaitinfo(2) and sigtimedwait(2)

2021-09-28 Thread Claudio Jeker
On Sun, Sep 26, 2021 at 02:36:02PM +0200, Mark Kettenis wrote:
> > Date: Fri, 24 Sep 2021 19:36:21 +0200
> > From: Rafael Sadowski 
> > 
> > I'm trying to port the more KDE stuff so my question is from porter
> > perspective.
> > 
> > I need sigwaitinfo(2)/sigtimedwait(2) and I found both functions in
> > lib/libc/gen/sigwait.c with the comment "need kernel to fill in more
> > siginfo_t bits first". Is the comment still up to date? If no, is it
> > possible to unlock the functions?
> 
> Still true.  These functions are somewhat underspecified by POSIX so
> it isn't really obvious whatadditional bits need to be filled in.
> Having examples of code that use these interfaces from ports could
> help with that.

Especially if the siginfo SIGCHLD bits are required. This will require
major work in the kernel since we don't have a method in place to
transport the exit information from the exiting process to the parent
signal handler.

-- 
:wq Claudio



normalize ldap DN in the config

2021-10-06 Thread Claudio Jeker
Run into this while setting up a new DN.
The DN in namespace only matches if it is normalized.
So it may be best to do this by default when adding a namespace.
With this using a capitalized namespace like "o=OpenBSD,c=CA" will
work. Also as a side note the rootdn is already normalized so no need
to fix that.

Totally unrelated but I could not resist to change the error check for
host from the somewhat funky <= 0 to a != 1 (host returns 1 on success and
0 and -1 on failure).

I will split this into two commits in the end.
-- 
:wq Claudio

Index: parse.y
===
RCS file: /cvs/src/usr.sbin/ldapd/parse.y,v
retrieving revision 1.40
diff -u -p -r1.40 parse.y
--- parse.y 2 May 2021 14:39:05 -   1.40
+++ parse.y 6 Oct 2021 16:56:50 -
@@ -207,7 +207,7 @@ conf_main   : LISTEN ON STRING port ssl ce
if (! interface($3, cert, >listeners,
$4, $5)) {
if (host($3, cert, >listeners,
-   $4, $5) <= 0) {
+   $4, $5) != 1) {
yyerror("invalid virtual ip or 
interface: %s", $3);
free($6);
free($3);
@@ -1206,15 +1206,16 @@ namespace_new(const char *suffix)
 
if ((ns = calloc(1, sizeof(*ns))) == NULL)
return NULL;
-   ns->suffix = strdup(suffix);
ns->sync = 1;
ns->cache_size = 1024;
ns->index_cache_size = 512;
+   ns->suffix = strdup(suffix);
if (ns->suffix == NULL) {
free(ns->suffix);
free(ns);
return NULL;
}
+   normalize_dn(ns->suffix);
TAILQ_INIT(>indices);
TAILQ_INIT(>request_queue);
SIMPLEQ_INIT(>acl);



bgpctl mrtdump adjustment

2021-09-22 Thread Claudio Jeker
In bgpd we do not follow the RFC8050 encoding for RIB_GENERIC_ADDPATH.
Mainly because it does not fit the way the code works and also because the
only other BGP implementation that seems to care about RIB_GENERIC_ADDPATH
does it the same way.

Because of this it makes no sense to parse RIB_GENERIC_ADDPATH strictly
per RFC8050 but instead parse it the way it is implemented.

While there cleanup some unused variables.
-- 
:wq Claudio

Index: mrtparser.c
===
RCS file: /cvs/src/usr.sbin/bgpctl/mrtparser.c,v
retrieving revision 1.15
diff -u -p -r1.15 mrtparser.c
--- mrtparser.c 27 Jul 2021 07:42:37 -  1.15
+++ mrtparser.c 22 Sep 2021 10:22:54 -
@@ -103,10 +103,8 @@ mrt_parse(int fd, struct mrt_parser *p, 
struct mrt_bgp_state*s;
struct mrt_bgp_msg  *m;
void*msg;
-   int  addpath;
 
while ((msg = mrt_read_msg(fd, ))) {
-   addpath = 0;
switch (ntohs(h.type)) {
case MSG_NULL:
case MSG_START:
@@ -376,7 +374,7 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
u_int32_t   snum, path_id = 0;
u_int16_t   cnt, i, afi;
u_int8_tsafi, aid;
-   int ret, addpath = 0;
+   int ret;
 
if (len < sizeof(snum) + 1)
return NULL;
@@ -417,6 +415,11 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
goto fail;
break;
case MRT_DUMP_V2_RIB_GENERIC_ADDPATH:
+   /*
+* RFC8050 handling for add-path has special handling for
+* RIB_GENERIC_ADDPATH but nobody implements it that way.
+* So just use the same way as for the other _ADDPATH types.
+*/
r->add_path = 1;
/* FALLTHROUGH */
case MRT_DUMP_V2_RIB_GENERIC:
@@ -434,16 +437,6 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
if ((aid = mrt_afi2aid(afi, safi, verbose)) == AID_UNSPEC)
goto fail;

-   /* RFC8050 handling for add-path */
-   if (r->add_path) {
-   if (len < sizeof(path_id))
-   goto fail;
-   memcpy(_id, b, sizeof(path_id));
-   b += sizeof(path_id);
-   len -= sizeof(path_id);
-   path_id = ntohl(path_id);
-   }
-
/* prefix */
ret = mrt_extract_prefix(b, len, aid, >prefix,
>prefixlen, verbose);
@@ -487,12 +480,9 @@ mrt_parse_v2_rib(struct mrt_hdr *hdr, vo
len -= sizeof(otm);
entries[i].originated = ntohl(otm);
 
-   /* RFC8050 handling for add-path */
-   if (r->add_path &&
-   ntohs(hdr->subtype) != MRT_DUMP_V2_RIB_GENERIC_ADDPATH) {
+   if (r->add_path) {
if (len < sizeof(path_id) + sizeof(alen))
goto fail;
-   addpath = 0;
memcpy(_id, b, sizeof(path_id));
b += sizeof(path_id);
len -= sizeof(path_id);



fix symlink read in openrsync

2021-10-22 Thread Claudio Jeker
flist_gen_dirent() does a fts_read and inside that tries to read the
symlink information. Now since fts_open did not specifiy FTS_NOCHDIR
the symlink_read call needs to use ent->fts_accpath instead of f->path
which was based on ent->fts_path.

OK?
-- 
:wq Claudio

Index: flist.c
===
RCS file: /cvs/src/usr.bin/rsync/flist.c,v
retrieving revision 1.34
diff -u -p -r1.34 flist.c
--- flist.c 2 Sep 2021 21:06:06 -   1.34
+++ flist.c 3 Sep 2021 13:09:13 -
@@ -992,7 +992,7 @@ flist_gen_dirent(struct sess *sess, char
/* Optionally copy link information. */
 
if (S_ISLNK(ent->fts_statp->st_mode)) {
-   f->link = symlink_read(f->path);
+   f->link = symlink_read(ent->fts_accpath);
if (f->link == NULL) {
ERRX1("symlink_read");
goto out;



Re: ixl(4): add checksum receive offloading

2021-10-22 Thread Claudio Jeker
On Fri, Oct 22, 2021 at 04:45:09PM +0200, Hrvoje Popovski wrote:
> On 22.10.2021. 16:09, Florian Obser wrote:
> > 
> > 
> > On 22 October 2021 13:55:20 CEST, Stuart Henderson  
> > wrote:
> >> On 2021/10/22 11:25, Jan Klemkow wrote:
> >>> this diff add hardware checksum offloading for the receive path of
> >>> ixl(4) interfaces.
> >>
> >> Would be good to have this tested with NFS if anyone has a way to do so.
> >> nics are probably better now but I'm pretty sure we have had problems
> >> with NFS and offloading in the past.
> > 
> > ospf as well.
> > 
> 
> ospf seems to work
> 
> 
> smc24# ospfctl show nei
> ID  Pri StateDeadTime Address Iface Uptime
> 10.1.1.11   FULL/BCKUP   00:00:30 192.168.15.123  ixl0  00:01:20
> 
> 
> 
> 10.11.0.0/16 192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 10.12.0.0/16 192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 10.13.0.0/16 192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 10.14.0.0/16 192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 10.15.0.0/16 192.168.15.11 Type 1 ext   Network   110
> 00:00:13
> 10.16.0.0/16 192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 10.17.0.0/16 192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 10.18.0.0/16 192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 
> 192.168.11.0/24  192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 192.168.12.0/24  192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 192.168.13.0/24  192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 192.168.14.0/24  192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 192.168.16.0/24  192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 192.168.17.0/24  192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 192.168.18.0/24  192.168.15.1  Type 1 ext   Network   110
> 00:00:13
> 

For ospfd tests you want to make sure that some of the ospf packets need
fragmenting. So this needs a sizeable network to hit this.

-- 
:wq Claudio



Re: libagentx: always initialize buf in ax_oidrange2string

2021-10-24 Thread Claudio Jeker
On Sun, Oct 24, 2021 at 06:31:29PM +0100, Martijn van Duren wrote:
> This diff should be superfluous with the next diff, but I don't think
> this should be left as is anyway.
> 
> It's not a big problem, since it's a static buffer and it gets
> initialized by previous calls, so it's always NUL-terminated, but
> it's not accurate.
> 
> OK?

OK claudio@
 
> martijn@
> 
> Index: ax.c
> ===
> RCS file: /cvs/src/lib/libagentx/ax.c,v
> retrieving revision 1.7
> diff -u -p -r1.7 ax.c
> --- ax.c  2 Jan 2021 01:06:31 -   1.7
> +++ ax.c  24 Oct 2021 17:31:03 -
> @@ -764,6 +764,8 @@ ax_oidrange2string(struct ax_oid *oid, u
>  
>   rest = sizeof(buf);
>   p = buf;
> + if (oid->aoi_idlen == 0)
> + (void)strlcpy(buf, "null", sizeof(buf));
>   for (i = 0; i < oid->aoi_idlen; i++) {
>   if (range_subid != 0 && range_subid - 1 == (uint8_t)i)
>   ret = snprintf(p, rest, ".[%u-%u]", oid->aoi_id[i],
> 
> 

-- 
:wq Claudio



Re: libagentx: Don't allow OIDs < 2

2021-10-24 Thread Claudio Jeker
On Sun, Oct 24, 2021 at 06:39:42PM +0100, Martijn van Duren wrote:
> libagentx currently allows OIDs with a length of 0.
> This isn't wrong from an agentx protocol point of view, but ber encoding
> can't handle OIDs with less then 2 elements, which makes it unable to
> map the values back to SNMP. netsnmp maps a null-oid to 0.0, but I don't
> think we should do that.
> 
> This diff also adds the check to a couple of other places where there
> was no active length checking prior. This is not an issue with current
> code using it (relayd(8)), because all OIDs are static, so are not
> susceptible for manipulation.
> 
> regress still passes.
> 
> OK?

Agreed that this is the right approach. agentx protocol spec was sloppy
in this regard. NULL OIDs only make sense for some messages but not for
others.

Diff looks OK.
 
> Index: agentx.h
> ===
> RCS file: /cvs/src/lib/libagentx/agentx.h,v
> retrieving revision 1.5
> diff -u -p -r1.5 agentx.h
> --- agentx.h  27 Oct 2020 18:24:01 -  1.5
> +++ agentx.h  24 Oct 2021 17:39:16 -
> @@ -36,6 +36,7 @@ enum agentx_request_type {
>  };
>  
>  #define AGENTX_MASTER_PATH "/var/agentx/master"
> +#define AGENTX_OID_MIN_LEN 2
>  #define AGENTX_OID_MAX_LEN 128
>  #define AGENTX_OID_INDEX_MAX_LEN 10
>  #define AGENTX_MIB2 1, 3, 6, 1, 2, 1
> Index: agentx.c
> ===
> RCS file: /cvs/src/lib/libagentx/agentx.c,v
> retrieving revision 1.13
> diff -u -p -r1.13 agentx.c
> --- agentx.c  23 Oct 2021 17:13:50 -  1.13
> +++ agentx.c  24 Oct 2021 17:39:17 -
> @@ -189,6 +189,8 @@ static int agentx_request(struct agentx 
>  static int agentx_request_cmp(struct agentx_request *,
>  struct agentx_request *);
>  static int agentx_strcat(char **, const char *);
> +static int agentx_oidfill(struct ax_oid *, const uint32_t[], size_t,
> +const char **);
>  
>  RB_PROTOTYPE_STATIC(ax_requests, agentx_request, axr_ax_requests,
>  agentx_request_cmp)
> @@ -362,25 +364,26 @@ agentx_session(struct agentx *ax, uint32
>  size_t oidlen, const char *descr, uint8_t timeout)
>  {
>   struct agentx_session *axs;
> - size_t i;
> + const char *errstr;
>  
> - if (oidlen > AGENTX_OID_MAX_LEN) {
> -#ifdef AX_DEBUG
> - agentx_log_ax_fatalx(ax, "%s: oidlen > %d", __func__,
> - AGENTX_OID_MAX_LEN);
> -#else
> - errno = EINVAL;
> - return NULL;
> -#endif
> - }
>   if ((axs = calloc(1, sizeof(*axs))) == NULL)
>   return NULL;
>  
>   axs->axs_ax = ax;
>   axs->axs_timeout = timeout;
> - for (i = 0; i < oidlen; i++)
> - axs->axs_oid.aoi_id[i] = oid[i];
> - axs->axs_oid.aoi_idlen = oidlen;
> + /* RFC 2741 section 6.2.1: may send a null Object Identifier */
> + if (oidlen == 0)
> + axs->axs_oid.aoi_idlen = oidlen;
> + else {
> + if (agentx_oidfill((>axs_oid), oid, oidlen,
> + ) == -1) {
> +#ifdef AX_DEBUG
> + agentx_log_ax_fatalx(ax, "%s: %s", __func__, errstr);
> +#else
> + return NULL;
> +#endif
> + }
> + }
>   axs->axs_descr.aos_string = (unsigned char *)strdup(descr);
>   if (axs->axs_descr.aos_string == NULL) {
>   free(axs);
> @@ -670,11 +673,21 @@ agentx_context_object_find(struct agentx
>  const uint32_t oid[], size_t oidlen, int active, int instance)
>  {
>   struct agentx_object *axo, axo_search;
> - size_t i;
> + const char *errstr;
>  
> - for (i = 0; i < oidlen; i++)
> - axo_search.axo_oid.aoi_id[i] = oid[i];
> - axo_search.axo_oid.aoi_idlen = oidlen;
> + if (agentx_oidfill(&(axo_search.axo_oid), oid, oidlen, ) == -1) {
> + if (oidlen > AGENTX_OID_MIN_LEN) {
> +#ifdef AX_DEBUG
> + agentx_log_axc_fatalx(axc, "%s: %s", __func__, errstr);
> +#else
> + agentx_log_axc_warnx(axc, "%s: %s", __func__, errstr);
> + return NULL;
> + }
> +#endif
> + if (oidlen == 1)
> + axo_search.axo_oid.aoi_id[0] = oid[0];
> + axo_search.axo_oid.aoi_idlen = oidlen;
> + }
>  
>   axo = RB_FIND(axc_objects, &(axc->axc_objects), _search);
>   while (axo == NULL && !instance && axo_search.axo_oid.aoi_idlen > 0) {
> @@ -691,11 +704,21 @@ agentx_context_object_nfind(struct agent
>  const uint32_t oid[], size_t oidlen, int active, int inclusive)
>  {
>   struct agentx_object *axo, axo_search;
> - size_t i;
> + const char *errstr;
>  
> - for (i = 0; i < oidlen; i++)
> - axo_search.axo_oid.aoi_id[i] = oid[i];
> - axo_search.axo_oid.aoi_idlen = oidlen;
> + if (agentx_oidfill(&(axo_search.axo_oid), oid, oidlen, ) == -1) {
> + if (oidlen > AGENTX_OID_MIN_LEN) {
> +#ifdef AX_DEBUG
> + 

rpki-client add regress print functions to main repo

2021-10-24 Thread Claudio Jeker
This diff adds the print functions from the regress test to rpki-client.
Currently not hooked up in rpki-client itself but that will follow soon.

-- 
:wq Claudio

Index: usr.sbin/rpki-client/extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.76
diff -u -p -r1.76 extern.h
--- usr.sbin/rpki-client/extern.h   24 Oct 2021 12:06:16 -  1.76
+++ usr.sbin/rpki-client/extern.h   24 Oct 2021 17:37:20 -
@@ -558,6 +558,13 @@ char   *x509_crl_get_aki(X509_CRL *, cons
 char   *x509_get_pubkey(X509 *, const char *);
 enum cert_purpose   x509_get_purpose(X509 *, const char *);
 
+/* printers */
+void   tal_print(const struct tal *);
+void   cert_print(const struct cert *);
+void   mft_print(const struct mft *);
+void   roa_print(const struct roa *);
+void   gbr_print(const struct gbr *);
+
 /* Output! */
 
 extern int  outformats;
Index: usr.sbin/rpki-client/print.c
===
RCS file: usr.sbin/rpki-client/print.c
diff -N usr.sbin/rpki-client/print.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ usr.sbin/rpki-client/print.c24 Oct 2021 17:30:47 -
@@ -0,0 +1,169 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2021 Claudio Jeker 
+ * Copyright (c) 2019 Kristaps Dzonsons 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "extern.h"
+
+static const char *
+pretty_key_id(char *hex)
+{
+   static char buf[128];   /* bigger than SHA_DIGEST_LENGTH * 3 */
+   size_t i;
+
+   for (i = 0; i < sizeof(buf) && *hex != '\0'; i++) {
+   if  (i % 3 == 2 && *hex != '\0')
+   buf[i] = ':';
+   else
+   buf[i] = *hex++;
+   }
+   if (i == sizeof(buf))
+   memcpy(buf + sizeof(buf) - 4, "...", 4);
+   return buf;
+}
+
+void
+tal_print(const struct tal *p)
+{
+   size_t   i;
+
+   for (i = 0; i < p->urisz; i++)
+   printf("%5zu: URI: %s\n", i + 1, p->uri[i]);
+}
+
+void
+cert_print(const struct cert *p)
+{
+   size_t   i;
+   char buf1[64], buf2[64];
+   int  sockt;
+   char tbuf[21];
+
+   printf("Subject key identifier: %s\n", pretty_key_id(p->ski));
+   if (p->aki != NULL)
+   printf("Authority key identifier: %s\n", pretty_key_id(p->aki));
+   if (p->aia != NULL)
+   printf("Authority info access: %s\n", p->aia);
+   if (p->mft != NULL)
+   printf("Manifest: %s\n", p->mft);
+   if (p->repo != NULL)
+   printf("caRepository: %s\n", p->repo);
+   if (p->notify != NULL)
+   printf("Notify URL: %s\n", p->notify);
+   if (p->pubkey != NULL)
+   printf("BGPsec P-256 ECDSA public key: %s\n", p->pubkey);
+   strftime(tbuf, sizeof(tbuf), "%FT%TZ", gmtime(>expires));
+   printf("Valid until: %s\n", tbuf);
+
+   printf("Subordinate Resources:\n");
+
+   for (i = 0; i < p->asz; i++)
+   switch (p->as[i].type) {
+   case CERT_AS_ID:
+   printf("%5zu: AS: %u\n", i + 1, p->as[i].id);
+   break;
+   case CERT_AS_INHERIT:
+   printf("%5zu: AS: inherit\n", i + 1);
+   break;
+   case CERT_AS_RANGE:
+   printf("%5zu: AS: %u -- %u\n", i + 1,
+   p->as[i].range.min, p->as[i].range.max);
+   break;
+   }
+
+   for (i = 0; i < p->ipsz; i++)
+   switch (p->ips[i].type) {
+   case CERT_IP_INHERIT:
+   printf("%5zu: IP: inherit\n", i + 1);
+   break;
+   case CERT_IP_ADDR:
+   ip_ad

fix ldapd bug when removing last attribute

2021-12-19 Thread Claudio Jeker
In LDAP there is two ways to remove an attribute.
One can remove an attribute by just naming the attribute but it is also
possible to remove a specific attribute: value combo.

In ldapd the latter is broken if the last attribute is removed because
the result of ldap_del_values() is an invalid encoding (empty sequence)
and with that the modification fails because validate_entry() fails.
The error is LDAP_INVALID_SYNTAX and I have noticed that in tools like
shelldap multiple times but never really connected the dots until now.

This is the minimal way of solving this. If ldap_del_values()
removes the last element use ldap_del_attribute() to remove the attribute
but to make this work the ober_scanf_elements() format has to be relaxed
since what we remove no longer parses with "{s(". Is this an acceptable
solution?

-- 
:wq Claudio

Index: attributes.c
===
RCS file: /cvs/src/usr.sbin/ldapd/attributes.c,v
retrieving revision 1.6
diff -u -p -r1.6 attributes.c
--- attributes.c24 Oct 2019 12:39:26 -  1.6
+++ attributes.c19 Dec 2021 12:12:48 -
@@ -181,7 +181,7 @@ ldap_del_attribute(struct ber_element *e
 
attr = entry->be_sub;
while (attr) {
-   if (ober_scanf_elements(attr, "{s(", ) != 0) {
+   if (ober_scanf_elements(attr, "{s", ) != 0) {
log_warnx("failed to parse attribute");
return -1;
}
@@ -240,6 +240,9 @@ ldap_del_values(struct ber_element *elm,
prev = v;
}
}
+
+   if (old_vals->be_sub == NULL)
+   return 1;
 
return 0;
 }
Index: modify.c
===
RCS file: /cvs/src/usr.sbin/ldapd/modify.c,v
retrieving revision 1.23
diff -u -p -r1.23 modify.c
--- modify.c24 Oct 2019 12:39:26 -  1.23
+++ modify.c19 Dec 2021 12:20:19 -
@@ -334,7 +334,8 @@ ldap_modify(struct request *req)
 */
if (vals->be_sub &&
vals->be_sub->be_type == BER_TYPE_OCTETSTRING) {
-   ldap_del_values(a, vals);
+   if (ldap_del_values(a, vals) == 1)
+   ldap_del_attribute(entry, attr);
} else {
ldap_del_attribute(entry, attr);
}
Index: validate.c
===
RCS file: /cvs/src/usr.sbin/ldapd/validate.c,v
retrieving revision 1.12
diff -u -p -r1.12 validate.c
--- validate.c  24 Oct 2019 12:39:26 -  1.12
+++ validate.c  19 Dec 2021 11:42:48 -
@@ -313,6 +313,7 @@ validate_entry(const char *dn, struct be
objclass = objclass->be_next;   /* skip attribute description */
for (a = objclass->be_sub; a != NULL; a = a->be_next) {
if (ober_get_string(a, ) != 0) {
+   log_debug("bad ObjectClass encoding");
rc = LDAP_INVALID_SYNTAX;
goto done;
}
@@ -396,6 +397,7 @@ validate_entry(const char *dn, struct be
 */
for (a = entry->be_sub; a != NULL; a = a->be_next) {
if (ober_scanf_elements(a, "{se{", , ) != 0) {
+   log_debug("bad attribue encoding");
rc = LDAP_INVALID_SYNTAX;
goto done;
}



Re: fix vmctl -B net -b bsd.rd to autoinstall

2021-12-22 Thread Claudio Jeker
On Wed, Dec 22, 2021 at 10:14:40AM -0500, Dave Voutila wrote:
> 
> Claudio Jeker  writes:
> 
> > I added support for vmctl -cL -B net -b bsd.rd -d disk.img to run the
> > autoinstall by emulating a PXE boot. In the commit
> > https://github.com/openbsd/src/commit/a13de4d12a4c9ba0edc05aab2ad635f782449229
> > the feature got removed over eagerly.
> >
> > This diff adds this back because I find this super practical.
> 
> Seems to add back more than that...see below.
> 

Those are becasue of warnings from the compiler and I do not like to send
out diffs for files that compile with a bunch of warnings.
I can split this out into an extra commit if people prefer that.

> >
> > Index: loadfile.h
> > ===
> > RCS file: /cvs/src/usr.sbin/vmd/loadfile.h,v
> > retrieving revision 1.15
> > diff -u -p -r1.15 loadfile.h
> > --- loadfile.h  16 Jun 2021 16:55:02 -  1.15
> > +++ loadfile.h  22 Dec 2021 14:34:06 -
> > @@ -80,7 +80,8 @@
> >  #define PML2_PAGE 0x13000
> >  #define NPTE_PG (PAGE_SIZE / sizeof(uint64_t))
> >
> > -int loadfile_elf(gzFile, struct vm_create_params *, struct vcpu_reg_state 
> > *);
> > +intloadfile_elf(gzFile, struct vm_create_params *, struct 
> > vcpu_reg_state *,
> > +   unsigned int);
> >
> >  size_t mread(gzFile, paddr_t, size_t);
> >
> > Index: loadfile_elf.c
> > ===
> > RCS file: /cvs/src/usr.sbin/vmd/loadfile_elf.c,v
> > retrieving revision 1.39
> > diff -u -p -r1.39 loadfile_elf.c
> > --- loadfile_elf.c  4 May 2021 10:48:51 -   1.39
> > +++ loadfile_elf.c  22 Dec 2021 14:38:55 -
> > @@ -118,7 +118,7 @@ static void setsegment(struct mem_segmen
> >  static int elf32_exec(gzFile, Elf32_Ehdr *, u_long *, int);
> >  static int elf64_exec(gzFile, Elf64_Ehdr *, u_long *, int);
> >  static size_t create_bios_memmap(struct vm_create_params *, bios_memmap_t 
> > *);
> > -static uint32_t push_bootargs(bios_memmap_t *, size_t);
> > +static uint32_t push_bootargs(bios_memmap_t *, size_t, bios_bootmac_t *);
> >  static size_t push_stack(uint32_t, uint32_t);
> >  static void push_gdt(void);
> >  static void push_pt_32(void);
> > @@ -264,13 +264,14 @@ push_pt_64(void)
> >   */
> >  int
> >  loadfile_elf(gzFile fp, struct vm_create_params *vcp,
> > -struct vcpu_reg_state *vrs)
> > +struct vcpu_reg_state *vrs, unsigned int bootdevice)
> >  {
> > int r, is_i386 = 0;
> > uint32_t bootargsz;
> > size_t n, stacksize;
> > u_long marks[MARK_MAX];
> > bios_memmap_t memmap[VMM_MAX_MEM_RANGES + 1];
> > +   bios_bootmac_t bm, *bootmac = NULL;
> >
> > if ((r = gzread(fp, , sizeof(hdr))) != sizeof(hdr))
> > return 1;
> > @@ -301,8 +302,12 @@ loadfile_elf(gzFile fp, struct vm_create
> > else
> > push_pt_64();
> >
> > +   if (bootdevice & VMBOOTDEV_NET) {
> > +   bootmac = 
> > +   memcpy(bootmac, vcp->vcp_macs[0], ETHER_ADDR_LEN);
> > +   }
> > n = create_bios_memmap(vcp, memmap);
> > -   bootargsz = push_bootargs(memmap, n);
> > +   bootargsz = push_bootargs(memmap, n, bootmac);
> > stacksize = push_stack(bootargsz, marks[MARK_END]);
> >
> > vrs->vrs_gprs[VCPU_REGS_RIP] = (uint64_t)marks[MARK_ENTRY];
> > @@ -382,9 +387,9 @@ create_bios_memmap(struct vm_create_para
> >   *  The size of the bootargs
> >   */
> >  static uint32_t
> > -push_bootargs(bios_memmap_t *memmap, size_t n)
> > +push_bootargs(bios_memmap_t *memmap, size_t n, bios_bootmac_t *bootmac)
> >  {
> > -   uint32_t memmap_sz, consdev_sz, i;
> > +   uint32_t memmap_sz, consdev_sz, bootmac_sz, i;
> > bios_consdev_t consdev;
> > uint32_t ba[1024];
> >
> > @@ -408,6 +413,15 @@ push_bootargs(bios_memmap_t *memmap, siz
> > memcpy([i + 3], , sizeof(bios_consdev_t));
> > i += consdev_sz / sizeof(int);
> >
> > +   if (bootmac) {
> > +   bootmac_sz = 3 * sizeof(int) + (sizeof(bios_bootmac_t) + 3) & 
> > ~3;
> > +   ba[i] = 0x7;   /* bootmac */
> > +   ba[i + 1] = bootmac_sz;
> > +   ba[i + 2] = bootmac_sz;
> > +   memcpy([i + 3], bootmac, sizeof(bios_bootmac_t));
> > +   i += bootmac_sz / sizeof(int);
> > +   }
> > +
> > ba[i++] = 0x; /* BOOTARG_END */
> >
> > write_mem(BOOTARGS_P

fix vmctl -B net -b bsd.rd to autoinstall

2021-12-22 Thread Claudio Jeker
I added support for vmctl -cL -B net -b bsd.rd -d disk.img to run the
autoinstall by emulating a PXE boot. In the commit
https://github.com/openbsd/src/commit/a13de4d12a4c9ba0edc05aab2ad635f782449229
the feature got removed over eagerly.

This diff adds this back because I find this super practical.
-- 
:wq Claudio

Index: loadfile.h
===
RCS file: /cvs/src/usr.sbin/vmd/loadfile.h,v
retrieving revision 1.15
diff -u -p -r1.15 loadfile.h
--- loadfile.h  16 Jun 2021 16:55:02 -  1.15
+++ loadfile.h  22 Dec 2021 14:34:06 -
@@ -80,7 +80,8 @@
 #define PML2_PAGE 0x13000
 #define NPTE_PG (PAGE_SIZE / sizeof(uint64_t))
 
-int loadfile_elf(gzFile, struct vm_create_params *, struct vcpu_reg_state *);
+intloadfile_elf(gzFile, struct vm_create_params *, struct vcpu_reg_state *,
+   unsigned int);
 
 size_t mread(gzFile, paddr_t, size_t);
 
Index: loadfile_elf.c
===
RCS file: /cvs/src/usr.sbin/vmd/loadfile_elf.c,v
retrieving revision 1.39
diff -u -p -r1.39 loadfile_elf.c
--- loadfile_elf.c  4 May 2021 10:48:51 -   1.39
+++ loadfile_elf.c  22 Dec 2021 14:38:55 -
@@ -118,7 +118,7 @@ static void setsegment(struct mem_segmen
 static int elf32_exec(gzFile, Elf32_Ehdr *, u_long *, int);
 static int elf64_exec(gzFile, Elf64_Ehdr *, u_long *, int);
 static size_t create_bios_memmap(struct vm_create_params *, bios_memmap_t *);
-static uint32_t push_bootargs(bios_memmap_t *, size_t);
+static uint32_t push_bootargs(bios_memmap_t *, size_t, bios_bootmac_t *);
 static size_t push_stack(uint32_t, uint32_t);
 static void push_gdt(void);
 static void push_pt_32(void);
@@ -264,13 +264,14 @@ push_pt_64(void)
  */
 int
 loadfile_elf(gzFile fp, struct vm_create_params *vcp,
-struct vcpu_reg_state *vrs)
+struct vcpu_reg_state *vrs, unsigned int bootdevice)
 {
int r, is_i386 = 0;
uint32_t bootargsz;
size_t n, stacksize;
u_long marks[MARK_MAX];
bios_memmap_t memmap[VMM_MAX_MEM_RANGES + 1];
+   bios_bootmac_t bm, *bootmac = NULL;
 
if ((r = gzread(fp, , sizeof(hdr))) != sizeof(hdr))
return 1;
@@ -301,8 +302,12 @@ loadfile_elf(gzFile fp, struct vm_create
else
push_pt_64();
 
+   if (bootdevice & VMBOOTDEV_NET) {
+   bootmac = 
+   memcpy(bootmac, vcp->vcp_macs[0], ETHER_ADDR_LEN);
+   }
n = create_bios_memmap(vcp, memmap);
-   bootargsz = push_bootargs(memmap, n);
+   bootargsz = push_bootargs(memmap, n, bootmac);
stacksize = push_stack(bootargsz, marks[MARK_END]);
 
vrs->vrs_gprs[VCPU_REGS_RIP] = (uint64_t)marks[MARK_ENTRY];
@@ -382,9 +387,9 @@ create_bios_memmap(struct vm_create_para
  *  The size of the bootargs
  */
 static uint32_t
-push_bootargs(bios_memmap_t *memmap, size_t n)
+push_bootargs(bios_memmap_t *memmap, size_t n, bios_bootmac_t *bootmac)
 {
-   uint32_t memmap_sz, consdev_sz, i;
+   uint32_t memmap_sz, consdev_sz, bootmac_sz, i;
bios_consdev_t consdev;
uint32_t ba[1024];
 
@@ -408,6 +413,15 @@ push_bootargs(bios_memmap_t *memmap, siz
memcpy([i + 3], , sizeof(bios_consdev_t));
i += consdev_sz / sizeof(int);
 
+   if (bootmac) {
+   bootmac_sz = 3 * sizeof(int) + (sizeof(bios_bootmac_t) + 3) & 
~3;
+   ba[i] = 0x7;   /* bootmac */
+   ba[i + 1] = bootmac_sz;
+   ba[i + 2] = bootmac_sz;
+   memcpy([i + 3], bootmac, sizeof(bios_bootmac_t));
+   i += bootmac_sz / sizeof(int);
+   } 
+
ba[i++] = 0x; /* BOOTARG_END */
 
write_mem(BOOTARGS_PAGE, ba, PAGE_SIZE);
@@ -485,7 +499,7 @@ mread(gzFile fp, paddr_t addr, size_t sz
const char *errstr = NULL;
int errnum = 0;
size_t ct;
-   size_t i, rd, osz;
+   size_t i, osz;
char buf[PAGE_SIZE];
 
/*
@@ -493,7 +507,6 @@ mread(gzFile fp, paddr_t addr, size_t sz
 * write_mem
 */
ct = 0;
-   rd = 0;
osz = sz;
if ((addr & PAGE_MASK) != 0) {
memset(buf, 0, sizeof(buf));
@@ -510,7 +523,6 @@ mread(gzFile fp, paddr_t addr, size_t sz
errnum, errstr);
return (0);
}
-   rd += ct;
 
if (write_mem(addr, buf, ct))
return (0);
@@ -538,7 +550,6 @@ mread(gzFile fp, paddr_t addr, size_t sz
errnum, errstr);
return (0);
}
-   rd += ct;
 
if (write_mem(addr, buf, ct))
return (0);
@@ -664,7 +675,6 @@ elf64_exec(gzFile fp, Elf64_Ehdr *elf, u
Elf64_Off off;
int i;
size_t sz;
-   int first;
int havesyms;
paddr_t minp = ~0, maxp = 0, pos = 0;
paddr_t offset 

Re: [External] : Re: make 'set skip on ...' dynamic

2021-12-22 Thread Claudio Jeker
On Sat, Dec 04, 2021 at 07:01:23PM +0100, Alexandr Nedvedicky wrote:
> Hello,
> 
> 
> On Fri, Dec 03, 2021 at 03:42:09PM +0100, Claudio Jeker wrote:
> > 
> > See comments below.
> > 
> > 
> > > +void
> > > +pfi_group_delmember(const char *group, struct ifnet *ifp)
> > > +{
> > > + struct pfi_kif  *gkif, *ikif;
> > > +
> > > + if ((gkif = pfi_kif_get(group, NULL)) == NULL ||
> > > + (ikif = pfi_kif_get(ifp->if_xname, NULL)) == NULL)
> > > + panic("%s: pfi_kif_get failed", __func__);
> > > + ikif->pfik_flags_new = ikif->pfik_flags & ~gkif->pfik_flags;
> > > +
> > > + pfi_group_change(group);
> > > +}
> > > +
> > 
> > This function is not quite right. For example:
> > 
> > ifconfig vio0 group foo group bar
> > pfctl -f - < > set skip on { foo bar }
> > block return
> > EOF
> > ping -qc2 100.64.1.2
> > 
> > PING 100.64.1.2 (100.64.1.2): 56 data bytes
> > 
> > --- 100.64.1.2 ping statistics ---
> > 2 packets transmitted, 2 packets received, 0.0% packet loss
> > round-trip min/avg/max/std-dev = 0.153/0.178/0.202/0.024 ms
> > 
> > 
> > Now lets remove just group bar from the interface.
> > 
> > ifconfig vio0 -group bar  
> > ping -qc2 100.64.1.2  
> > 
> > PING 100.64.1.2 (100.64.1.2): 56 data bytes
> > ping: sendmsg: Permission denied
> > ping: wrote 100.64.1.2 64 chars, ret=-1
> > ping: sendmsg: Permission denied
> > ping: wrote 100.64.1.2 64 chars, ret=-1
> >  
> > pfi_group_delmember() does not take into consideration other groups
> > (including the interface itself) that may still allow PFI_IFLAG_SKIP.
> > It just clears the flag.
> > 
> > I think on delete the flag needs to be recalculated after the group has
> > been removed. Not sure if this is easy possible though.
> > 
> 
> yes, you are absolutely right. the current logic around pfi_skip_if() is
> bit convoluted. in  order to fix it I must rework pfi_xcommit() and 
> related
> set_flags()/clear_flags() functions. The idea is to let pfi_xcommit() to
> combine skip flags from all groups, which are attached to interface.
> 
> 
> updated diff is attached.

One comment below but this diff is OK claudio@
 
> thanks and
> regards
> sashan
> 
> 8<---8<---8<--8<
>  void
>  pfi_xcommit(void)
>  {
> - struct pfi_kif  *p;
> + struct pfi_kif  *p, *gkif;
> + struct ifg_list *g;
> + struct ifnet*ifp;
> + size_t n;
>  
> - RB_FOREACH(p, pfi_ifhead, _ifs)
> + RB_FOREACH(p, pfi_ifhead, _ifs) {
>   p->pfik_flags = p->pfik_flags_new;
> + n = strlen(p->pfik_name);
> + ifp = p->pfik_ifp;
> + /*
> +  * if kif is backed by existing interface, then we must use
> +  * skip flags found in groups. We use pfik_flags_new, otherwise
> +  * we would need to do two RB_FOREACH() passes: the first to
> +  * commit group changes the second to commit flag changes for
> +  * interfaces.
> +  */
> + if (isdigit(p->pfik_name[n - 1]) && ifp != NULL)

No other code in pf_if.c is checking both pfik_name and ifp != NULL in
similar situations.  I think you should skip the isdigit() check here.
If there is a real interface connected to a pfi_kif than it should be updated.
Lets not introduce more complexity here.

> + TAILQ_FOREACH(g, >if_groups, ifgl_next) {
> + gkif =
> + (struct pfi_kif *)g->ifgl_group->ifg_pf_kif;
> + KASSERT(gkif != NULL);
> + p->pfik_flags |= gkif->pfik_flags_new;
> + }
> + }
>  }

-- 
:wq Claudio



Re: rpki-client: check ipAddrBlock and autonomousSysNum for criticality

2021-12-25 Thread Claudio Jeker
On Sat, Dec 25, 2021 at 11:36:50AM +0100, Theo Buehler wrote:
> These extensions MUST be marked critical by the sections of the spec
> mentioned in the cryptowarnx(). That's determined by the ASN1_BOOLEAN
> that is extracted and ignored after the FIXME a few lines below each of
> the two hunks. Rather than getting the info from there, it's easier to
> use an API call that checks what was already parsed by d2i_X509().

I like this a lot. OK claudio@

I would love to get rid of X509_V_FLAG_IGNORE_CRITICAL and use a callback
to ensure the right extensions are critical but I never managed to
understand how the X509_verify_cert() callback actually works.
Documentation seems to be non-existent.
 
> Index: cert.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
> retrieving revision 1.47
> diff -u -p -r1.47 cert.c
> --- cert.c5 Nov 2021 10:50:41 -   1.47
> +++ cert.c24 Dec 2021 23:40:55 -
> @@ -588,6 +588,12 @@ sbgp_assysnum(struct parse *p, X509_EXTE
>   int  dsz, rc = 0, i, ptag;
>   long plen;
>  
> + if (!X509_EXTENSION_get_critical(ext)) {
> + cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
> + "extension not critical", p->fn);
> + goto out;
> + }
> +
>   if ((dsz = i2d_X509_EXTENSION(ext, )) < 0) {
>   cryptowarnx("%s: RFC 6487 section 4.8.11: autonomousSysNum: "
>   "failed extension parse", p->fn);
> @@ -890,6 +896,12 @@ sbgp_ipaddrblk(struct parse *p, X509_EXT
>   ASN1_SEQUENCE_ANY   *seq = NULL, *sseq = NULL;
>   const ASN1_TYPE *t = NULL;
>   int  i;
> +
> + if (!X509_EXTENSION_get_critical(ext)) {
> + cryptowarnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> + "extension not critical", p->fn);
> + goto out;
> + }
>  
>   if ((dsz = i2d_X509_EXTENSION(ext, )) < 0) {
>   cryptowarnx("%s: RFC 6487 section 4.8.10: sbgp-ipAddrBlock: "
> 

-- 
:wq Claudio



Re: rpki-client pass real filename from parser back to parent

2022-01-04 Thread Claudio Jeker
On Tue, Jan 04, 2022 at 04:57:23PM +0100, Theo Buehler wrote:
> On Tue, Jan 04, 2022 at 04:15:56PM +0100, Claudio Jeker wrote:
> > This is another diff on the way to having a validated repo.
> > Pass the filename of the entity which was parsed back to the parent.
> > With this we can move the filepath_add() call from entity_write_req()
> > to entity_process(). As a side-effect the "Already visited" check is moved
> > after parsing so a file may be reparsed before being ignored. I doubt this
> > causes an issue.
> > 
> > On top of this change how entp->file is passed to the individual parser
> > functions. Just pass the filename to those functions. Only exception for
> > now is proc_parser_root_cert() since it accesses more of the entp.
> > 
> > Again this is done to make it possible to have the parser decide which
> > path to use for accessing a file. For now this is just shuffling code but
> > once the code has two places to look for a file this will be all needed.
> 
> ok tb
> 
> This will need a little bit of work on top of the verify_cb() commit.
> Something like
> 
> sed -i '/set_app_data/s/entp->/(char *)/' parser.c
> 
> should do it (or whichever way you want to deal with the const issue
> arising from the fact X509_STORE_CTX_set_app_data() taking a non-const
> void * as a second argument).

I actually removed the const from the various function prototypes. While
nice it is not needed there and I prefer that over extra casts because of
const.

-- 
:wq Claudio

Index: main.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.170
diff -u -p -r1.170 main.c
--- main.c  29 Dec 2021 11:37:57 -  1.170
+++ main.c  4 Jan 2022 13:39:31 -
@@ -132,12 +132,6 @@ entity_write_req(const struct entity *en
 {
struct ibuf *b;
 
-   if (filepath_add(, ent->file) == 0) {
-   warnx("%s: File already visited", ent->file);
-   entity_queue--;
-   return;
-   }
-
b = io_new_buffer();
io_simple_buffer(b, >type, sizeof(ent->type));
io_simple_buffer(b, >talid, sizeof(ent->talid));
@@ -467,6 +461,7 @@ entity_process(struct ibuf *b, struct st
struct cert *cert;
struct mft  *mft;
struct roa  *roa;
+   char*file;
int  c;
 
/*
@@ -476,6 +471,14 @@ entity_process(struct ibuf *b, struct st
 * We follow that up with whether the resources didn't parse.
 */
io_read_buf(b, , sizeof(type));
+   io_read_str(b, );
+
+   if (filepath_add(, file) == 0) {
+   warnx("%s: File already visited", file);
+   free(file);
+   entity_queue--;
+   return;
+   }
 
switch (type) {
case RTYPE_TAL:
@@ -544,6 +547,7 @@ entity_process(struct ibuf *b, struct st
errx(1, "unknown entity type %d", type);
}
 
+   free(file);
entity_queue--;
 }
 
Index: parser.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.31
diff -u -p -r1.31 parser.c
--- parser.c4 Jan 2022 15:37:23 -   1.31
+++ parser.c4 Jan 2022 18:17:49 -
@@ -109,7 +109,7 @@ verify_cb(int ok, X509_STORE_CTX *store_
  * Returns the roa on success, NULL on failure.
  */
 static struct roa *
-proc_parser_roa(struct entity *entp, const unsigned char *der, size_t len)
+proc_parser_roa(char *file, const unsigned char *der, size_t len)
 {
struct roa  *roa;
X509*x509;
@@ -119,10 +119,10 @@ proc_parser_roa(struct entity *entp, con
STACK_OF(X509_CRL)  *crls;
struct crl  *crl;
 
-   if ((roa = roa_parse(, entp->file, der, len)) == NULL)
+   if ((roa = roa_parse(, file, der, len)) == NULL)
return NULL;
 
-   a = valid_ski_aki(entp->file, , roa->ski, roa->aki);
+   a = valid_ski_aki(file, , roa->ski, roa->aki);
build_chain(a, );
crl = get_crl(a);
build_crls(crl, );
@@ -131,7 +131,7 @@ proc_parser_roa(struct entity *entp, con
if (!X509_STORE_CTX_init(ctx, NULL, x509, NULL))
cryptoerrx("X509_STORE_CTX_init");
X509_STORE_CTX_set_verify_cb(ctx, verify_cb);
-   if (!X509_STORE_CTX_set_app_data(ctx, entp->file))
+   if (!X509_STORE_CTX_set_app_data(ctx, file))
cryptoerrx("X509_STORE_CTX_set_app_data");
X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CRL_CHECK);
X509_STORE_CTX_set_depth(ctx, MAX_CERT_DEPTH);
@@ -142,8 +142,7 @@ proc_parser_roa(struct entity *e

rpki-client parser refactor

2022-01-05 Thread Claudio Jeker
This changes the last proc_parser function over to not pass the entity to
the function. In this case apart from file we also need to pass the public
key of the TA and the tal identifier.

Change is mechanical and makes all callers work the same way.
-- 
:wq Claudio

Index: parser.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.32
diff -u -p -r1.32 parser.c
--- parser.c4 Jan 2022 18:41:32 -   1.32
+++ parser.c5 Jan 2022 09:49:07 -
@@ -246,8 +246,7 @@ proc_parser_mft(char *file, const unsign
  * parse failure.
  */
 static struct cert *
-proc_parser_cert(char *file, const unsigned char *der,
-size_t len)
+proc_parser_cert(char *file, const unsigned char *der, size_t len)
 {
struct cert *cert;
X509*x509;
@@ -325,8 +324,8 @@ proc_parser_cert(char *file, const unsig
  * parse failure.
  */
 static struct cert *
-proc_parser_root_cert(const struct entity *entp, const unsigned char *der,
-size_t len)
+proc_parser_root_cert(char *file, const unsigned char *der, size_t len,
+unsigned char *pkey, size_t pkeysz, int talid)
 {
charsubject[256];
ASN1_TIME   *notBefore, *notAfter;
@@ -334,52 +333,49 @@ proc_parser_root_cert(const struct entit
struct cert *cert;
X509*x509;
 
-   assert(entp->data != NULL);
-
/* Extract certificate data and X509. */
 
-   cert = ta_parse(, entp->file, der, len, entp->data, entp->datasz);
+   cert = ta_parse(, file, der, len, pkey, pkeysz);
if (cert == NULL)
return NULL;
 
if ((name = X509_get_subject_name(x509)) == NULL) {
-   warnx("%s Unable to get certificate subject", entp->file);
+   warnx("%s Unable to get certificate subject", file);
goto badcert;
}
if (X509_NAME_oneline(name, subject, sizeof(subject)) == NULL) {
-   warnx("%s: Unable to parse certificate subject name",
-   entp->file);
+   warnx("%s: Unable to parse certificate subject name", file);
goto badcert;
}
if ((notBefore = X509_get_notBefore(x509)) == NULL) {
warnx("%s: certificate has invalid notBefore, subject='%s'",
-   entp->file, subject);
+   file, subject);
goto badcert;
}
if ((notAfter = X509_get_notAfter(x509)) == NULL) {
warnx("%s: certificate has invalid notAfter, subject='%s'",
-   entp->file, subject);
+   file, subject);
goto badcert;
}
if (X509_cmp_current_time(notBefore) != -1) {
-   warnx("%s: certificate not yet valid, subject='%s'", entp->file,
+   warnx("%s: certificate not yet valid, subject='%s'", file,
subject);
goto badcert;
}
if (X509_cmp_current_time(notAfter) != 1)  {
-   warnx("%s: certificate has expired, subject='%s'", entp->file,
+   warnx("%s: certificate has expired, subject='%s'", file,
subject);
goto badcert;
}
-   if (!valid_ta(entp->file, , cert)) {
+   if (!valid_ta(file, , cert)) {
warnx("%s: certificate not a valid ta, subject='%s'",
-   entp->file, subject);
+   file, subject);
goto badcert;
}
 
X509_free(x509);
 
-   cert->talid = entp->talid;
+   cert->talid = talid;
 
/*
 * Add valid roots to the RPKI auth tree.
@@ -589,7 +585,9 @@ parse_entity(struct entityq *q, struct m
break;
case RTYPE_CER:
if (entp->data != NULL)
-   cert = proc_parser_root_cert(entp, f, flen);
+   cert = proc_parser_root_cert(entp->file,
+   f, flen, entp->data, entp->datasz,
+   entp->talid);
else
cert = proc_parser_cert(entp->file, f, flen);
c = (cert != NULL);



rpki-client simplify code a bit

2021-12-21 Thread Claudio Jeker
The limiter for repository count under a TA only makes sense for
repositories referenced from certs but less so for the actual TA. So
remove the logic from ta_lookup() and friends and make the code simpler.
There is no risk in doing so since there is only one TA and one
ta_lookup() done per TAL and the MAX_REPO_PER_TAL check can never trigger.

-- 
:wq Claudio

Index: repo.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v
retrieving revision 1.15
diff -u -p -r1.15 repo.c
--- repo.c  7 Dec 2021 12:46:47 -   1.15
+++ repo.c  21 Dec 2021 15:20:26 -
@@ -381,7 +381,7 @@ ta_fetch(struct tarepo *tr)
 }
 
 static struct tarepo *
-ta_get(struct tal *tal, int nofetch)
+ta_get(struct tal *tal)
 {
struct tarepo *tr;
 
@@ -405,7 +405,7 @@ ta_get(struct tal *tal, int nofetch)
tal->urisz = 0;
tal->uri = NULL;
 
-   if (noop || nofetch) {
+   if (noop) {
tr->state = REPO_DONE;
logx("ta/%s: using cache", tr->descr);
/* there is nothing in the queue so no need to flush */
@@ -1087,7 +1087,6 @@ struct repo *
 ta_lookup(int id, struct tal *tal)
 {
struct repo *rp;
-   int  nofetch = 0;
 
/* Look up in repository table. (Lookup should actually fail here) */
SLIST_FOREACH(rp, , entry) {
@@ -1099,13 +1098,7 @@ ta_lookup(int id, struct tal *tal)
if ((rp->repouri = strdup(tal->descr)) == NULL)
err(1, NULL);
 
-   if (++talrepocnt[id] >= MAX_REPO_PER_TAL) {
-   if (talrepocnt[id] == MAX_REPO_PER_TAL)
-   warnx("too many repositories under %s", tals[id]);
-   nofetch = 1;
-   }
-
-   rp->ta = ta_get(tal, nofetch);
+   rp->ta = ta_get(tal);
 
return rp;
 }



more rpki-client cleanup

2021-12-21 Thread Claudio Jeker
In the roa parser the handling of maxlen is overly complex.
Just set maxlen to addr.prefixlen before parsing the maxlength option.
If present it will override maxlen with the new value and with that the
ternary confusion at the end can be removed.

-- 
:wq Claudio

Index: roa.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/roa.c,v
retrieving revision 1.33
diff -u -p -r1.33 roa.c
--- roa.c   3 Dec 2021 12:56:19 -   1.33
+++ roa.c   21 Dec 2021 18:09:27 -
@@ -50,7 +50,7 @@ roa_parse_addr(const ASN1_OCTET_STRING *
size_t   dsz = os->length;
int  rc = 0;
const ASN1_TYPE *t;
-   const ASN1_INTEGER  *maxlength = NULL;
+   const ASN1_INTEGER  *maxlength;
long maxlen;
struct ip_addr   addr;
struct roa_ip   *res;
@@ -83,6 +83,7 @@ roa_parse_addr(const ASN1_OCTET_STRING *
"invalid IP address", p->fn);
goto out;
}
+   maxlen = addr.prefixlen;
 
if (sk_ASN1_TYPE_num(seq) == 2) {
t = sk_ASN1_TYPE_value(seq, 1);
@@ -115,7 +116,7 @@ roa_parse_addr(const ASN1_OCTET_STRING *
 
res->addr = addr;
res->afi = afi;
-   res->maxlength = (maxlength == NULL) ? addr.prefixlen : maxlen;
+   res->maxlength = maxlen;
ip_roa_compose_ranges(res);
 
rc = 1;



rpki-client, stop using size_t for ids

2021-12-21 Thread Claudio Jeker
For some reasons various ids were stored as size_t (probably because once
they used to be the index in an array). This is just silly and annoyed me
for long enough. I think this fixes all of them.

While there also stop using size_t for maxlength of a prefix. Everywhere
else the code uses just a unsigned char for that so do it there as well.
Shuffle struct a little bit in hope for better packing.

Seems to work with RRDP and RSYNC.
-- 
:wq Claudio

Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.98
diff -u -p -r1.98 extern.h
--- extern.h25 Nov 2021 14:03:40 -  1.98
+++ extern.h21 Dec 2021 17:26:16 -
@@ -179,10 +179,10 @@ struct mft {
  */
 struct roa_ip {
enum afi afi; /* AFI value */
-   size_t   maxlength; /* max length or zero */
+   struct ip_addr   addr; /* the address prefix itself */
unsigned charmin[16]; /* full range minimum */
unsigned charmax[16]; /* full range maximum */
-   struct ip_addr   addr; /* the address prefix itself */
+   unsigned charmaxlength; /* max length or zero */
 };
 
 /*
@@ -498,8 +498,8 @@ void proc_rrdp(int);
 
 /* Repository handling */
 int filepath_add(struct filepath_tree *, char *);
-voidrrdp_save_state(size_t, struct rrdp_session *);
-int rrdp_handle_file(size_t, enum publish_type, char *,
+voidrrdp_save_state(unsigned int, struct rrdp_session *);
+int rrdp_handle_file(unsigned int, enum publish_type, char *,
char *, size_t, char *, size_t);
 char   *repo_filename(const struct repo *, const char *);
 struct repo*ta_lookup(int, struct tal *);
@@ -508,15 +508,15 @@ intrepo_queued(struct repo *, struct 
 voidrepo_cleanup(struct filepath_tree *);
 voidrepo_free(void);
 
-voidrsync_finish(size_t, int);
-voidhttp_finish(size_t, enum http_result, const char *);
-voidrrdp_finish(size_t, int);
-
-voidrsync_fetch(size_t, const char *, const char *);
-voidhttp_fetch(size_t, const char *, const char *, int);
-voidrrdp_fetch(size_t, const char *, const char *,
+voidrsync_finish(unsigned int, int);
+voidhttp_finish(unsigned int, enum http_result, const char *);
+voidrrdp_finish(unsigned int, int);
+
+voidrsync_fetch(unsigned int, const char *, const char *);
+voidhttp_fetch(unsigned int, const char *, const char *, int);
+voidrrdp_fetch(unsigned int, const char *, const char *,
struct rrdp_session *);
-voidrrdp_http_done(size_t, enum http_result, const char *);
+voidrrdp_http_done(unsigned int, enum http_result, const char *);
 
 int repo_next_timeout(int);
 voidrepo_check_timeout(void);
Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.50
diff -u -p -r1.50 http.c
--- http.c  10 Nov 2021 09:13:30 -  1.50
+++ http.c  21 Dec 2021 17:19:29 -
@@ -140,7 +140,7 @@ struct http_request {
char*host;
char*port;
const char  *path;  /* points into uri */
-   size_t   id;
+   unsigned int id;
int  outfd;
int  redirect_loop;
 };
@@ -150,7 +150,7 @@ TAILQ_HEAD(http_req_queue, http_request)
 static struct http_conn_list   active = LIST_HEAD_INITIALIZER(active);
 static struct http_conn_list   idle = LIST_HEAD_INITIALIZER(idle);
 static struct http_req_queue   queue = TAILQ_HEAD_INITIALIZER(queue);
-static size_t http_conn_count;
+static unsigned int http_conn_count;
 
 static struct msgbuf msgq;
 static struct sockaddr_storage http_bindaddr;
@@ -159,10 +159,10 @@ static uint8_t *tls_ca_mem;
 static size_t tls_ca_size;
 
 /* HTTP request API */
-static voidhttp_req_new(size_t, char *, char *, int, int);
+static voidhttp_req_new(unsigned int, char *, char *, int, int);
 static voidhttp_req_free(struct http_request *);
-static voidhttp_req_done(size_t, enum http_result, const char *);
-static voidhttp_req_fail(size_t);
+static voidhttp_req_done(unsigned int, enum http_result, const char *);
+static voidhttp_req_fail(unsigned int);
 static int http_req_schedule(struct http_request *);
 
 /* HTTP connection API */
@@ -509,7 +509,8 @@ http_resolv(struct addrinfo **res, const
  * Create and queue a new request.
  */
 static void
-http_req_new(size_t id, char *uri, char *modified_since, int count, int outfd)
+http_req_new(unsigned int id, char *uri, char *modified_since, int count,
+int outfd)
 {
struct http_request *req;
   

rpki-client refactor common repo code

2021-12-23 Thread Claudio Jeker
Create a common repo_done() function which does the entiyq_flush and in
the case of RRDP the fallback to rsync. This simplifies the code and will
help to add the repo info to the parser process.

One difference between this and the original version is the case when a
RRDP repository merge fails. Before the code would just give up while now
it will also fall back to rsync. I think that's fine in the end if
anything with RRDP fails rpki-client should try rsync before giving up.

Apart from the the code should behave the same.
-- 
:wq Claudio

Index: repo.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v
retrieving revision 1.17
diff -u -p -r1.17 repo.c
--- repo.c  22 Dec 2021 09:35:14 -  1.17
+++ repo.c  23 Dec 2021 15:09:36 -
@@ -88,7 +88,7 @@ struct tarepo {
 };
 SLIST_HEAD(, tarepo)   tarepos = SLIST_HEAD_INITIALIZER(tarepos);
 
-struct repo {
+struct repo {
SLIST_ENTRY(repo)entry;
char*repouri;
char*notifyuri;
@@ -105,6 +105,8 @@ SLIST_HEAD(, repo)  repos = SLIST_HEAD_IN
 /* counter for unique repo id */
 unsigned int   repoid;
 
+static struct rsyncrepo*rsync_get(const char *, int);
+
 /*
  * Database of all file path accessed during a run.
  */
@@ -271,6 +273,49 @@ repo_mkpath(char *file)
 }
 
 /*
+ * Return the state of a repository.
+ */
+static enum repo_state
+repo_state(struct repo *rp)
+{
+   if (rp->ta)
+   return rp->ta->state;
+   if (rp->rsync)
+   return rp->rsync->state;
+   if (rp->rrdp)
+   return rp->rrdp->state;
+   errx(1, "%s: bad repo", rp->repouri);
+}
+
+/*
+ * Function called once a repository is done with the sync. Either
+ * successfully or after failure.
+ */
+static void
+repo_done(const void *vp, int ok)
+{
+   struct repo *rp;
+
+   SLIST_FOREACH(rp, , entry) {
+   if (rp->ta == vp)
+   entityq_flush(>queue, rp);
+   if (rp->rsync == vp)
+   entityq_flush(>queue, rp);
+   if (rp->rrdp == vp) {
+   if (!ok) {
+   /* try to fall back to rsync */
+   rp->rrdp = NULL;
+   rp->rsync = rsync_get(rp->repouri, 0);
+   /* need to check if it was already loaded */
+   if (repo_state(rp) != REPO_LOADING)
+   entityq_flush(>queue, rp);
+   } else
+   entityq_flush(>queue, rp);
+   }
+   }
+}
+
+/*
  * Build TA file name based on the repo info.
  * If temp is set add Xs for mkostemp.
  */
@@ -344,14 +389,10 @@ ta_fetch(struct tarepo *tr)
}
 
if (tr->uriidx >= tr->urisz) {
-   struct repo *rp;
-
tr->state = REPO_FAILED;
logx("ta/%s: fallback to cache", tr->descr);
 
-   SLIST_FOREACH(rp, , entry)
-   if (rp->ta == tr)
-   entityq_flush(>queue, rp);
+   repo_done(tr, 0);
return;
}
 
@@ -406,9 +447,9 @@ ta_get(struct tal *tal)
tal->uri = NULL;
 
if (noop) {
-   tr->state = REPO_DONE;
+   tr->state = REPO_FAILED;
logx("ta/%s: using cache", tr->descr);
-   /* there is nothing in the queue so no need to flush */
+   repo_done(tr, 0);
} else {
/* try to create base directory */
if (mkpath(tr->basedir) == -1)
@@ -471,9 +512,9 @@ rsync_get(const char *uri, int nofetch)
rr->basedir = repo_dir(repo, "rsync", 0);
 
if (noop || nofetch) {
-   rr->state = REPO_DONE;
+   rr->state = REPO_FAILED;
logx("%s: using cache", rr->basedir);
-   /* there is nothing in the queue so no need to flush */
+   repo_done(rr, 0);
} else {
/* create base directory */
if (mkpath(rr->basedir) == -1) {
@@ -541,9 +582,9 @@ rrdp_get(const char *uri, int nofetch)
RB_INIT(>deleted);
 
if (noop || nofetch) {
-   rr->state = REPO_DONE;
+   rr->state = REPO_FAILED;
logx("%s: using cache", rr->notifyuri);
-   /* there is nothing in the queue so no need to flush */
+   repo_done(rr, 0);
} else {
/* create base directory */
if (mkpath(rr->basedir) == -1) {
@@ -629,21 +670,6 @@ repo_alloc(int talid)
 }
 
 /*
- * Return the state of a repository.
- */
-static enum repo_state
-repo_state(struct repo *rp)
-{
-   if (rp->ta)
-   return rp->ta->state;
-   if (rp->rrdp)
-   return rp->rrdp->state;
-   if (rp->rsync)
-   

Re: uhidppctl(8)

2021-12-23 Thread Claudio Jeker
On Thu, Dec 23, 2021 at 07:50:24AM +, Raf Czlonka wrote:
> On Wed, Dec 22, 2021 at 08:32:16AM GMT, Claudio Jeker wrote:
> > On Tue, Dec 21, 2021 at 03:49:47PM -0500, jwinnie@tilde.institute wrote:
> > > 
> > > Hello OpenBSD developers,
> > > 
> > > I am interested in contributing to improve the uhidpp(4)
> > > (Logitech Unifying Reciever) support in OpenBSD.
> > > 
> > > Currently, the uhidpp(4) driver only handles detecting certain
> > > sensors, but I would like more robust support for these devices,
> > > including:
> > > 
> > > * pairing and unpairing devices on the command-line
> > > * controlling the scrolling speed/auxiliary buttons of wireless mice
> > > 
> > > Do you know where I should start? Should I work on the uhidpp(4)
> > > driver, or should I go ahead and start writing a command-line utility,
> > > like uhidppctl(8)?
> > 
> > I doubt we want a uhidppctl(8) unless it is really necessary.
> > I would expect wsmouse(4) to handle the controlling of scrolling
> > speed and auxiliary buttons.
> 
> Hi Claudio,
> 
> I had to do pair some devices recently for both Logitech Unifying
> receiver as well as How Dell Universal Pairing receiver (out of
> scope here), and it was a bit of a faff having to source another
> machine and OS. So, purely from a user perspective, given that a
> single receiver can pair up to six devices, it would be nice not
> having to use another machine/OS to do the pairing step :^)

I agree with you and I did not talk about pairing devices in my reply
because this is a more complex topic. We only had the now removed netbt
stack that had pairing implemented and it was rather bad to use.
Device pairing should work a bit like how WiFi join works.
Another thing to not forget is that all of our wifi adapters use
ifconifg(4) for configuration. We don't ship a iwmctl, iwnctl, iwxctl,
bwfmctl, ralctl, runctl, wiconfig and mtwctl. Sure currently this is only
about Logitech so uhidppctl(8) works but what when more such adapters
are added?

-- 
:wq Claudio



Re: rpki-client: check ipAddrBlock and autonomousSysNum for criticality

2021-12-28 Thread Claudio Jeker
On Mon, Dec 27, 2021 at 12:23:32PM +0100, Theo Buehler wrote:
> On Sat, Dec 25, 2021 at 05:48:53PM +0100, Claudio Jeker wrote:
> [...]
> > I would love to get rid of X509_V_FLAG_IGNORE_CRITICAL and use a callback
> > to ensure the right extensions are critical but I never managed to
> > understand how the X509_verify_cert() callback actually works.
> > Documentation seems to be non-existent.
> 
> My understanding is that X509_V_FLAG_IGNORE_CRITICAL is a big hammer
> that was necessary as long as libcrypto didn't know about the RFC 3779
> extensions. Without it X509_verify_cert() would error on encountering
> them. This changed shortly after Gouveia when we enabled the RFC 3779
> code in libcrypto. I think setting the flag is no longer appropriate in
> -current.
> 
> Below is a diff that removes X509_V_FLAG_IGNORE_CRITICAL and adds a
> debug verify callback that intercepts unhandled critical extensions. It
> lets through the RFC 3779 extensions and errors on everything else.
> 
> If you run with this on -current, the callback doesn't print anything.
> On -stable you'll see that it logs at least one of the two extensions
> per cert while X509_verify_cert() is walking through the chains.
> 
> If we want to drop X509_V_FLAG_IGNORE_CRITICAL, something like this
> will be needed as long as rpki-client wants to support LibreSSL < 3.5.
> The idea is that we handle RFC 3779 extensions ourselves, so we can
> safely ignore them in the verifier. All other critical extensions that
> neither rpki-client nor libcrypto know about should be verification
> failures.
> 
> You can play with this on -current by disabling RFC 3779 again: remove
> or comment the #ifndef LIBRESSL_CRYPTO_INTERNAL around OPENSSL_NO_RFC3779
> in lib/libcrypto/opensslfeatures.h then make clean, make includes, make
> and make install.

I like this. A few questions inline.

> Index: parser.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
> retrieving revision 1.28
> diff -u -p -r1.28 parser.c
> --- parser.c  4 Nov 2021 18:26:48 -   1.28
> +++ parser.c  27 Dec 2021 08:37:53 -
> @@ -34,6 +34,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  #include "extern.h"
>  
> @@ -45,6 +46,102 @@ static X509_STORE_CTX *ctx;
>  static struct auth_tree  auths = RB_INITIALIZER();
>  static struct crl_treecrlt = RB_INITIALIZER();
>  
> +static int
> +generic_verify(int ok, X509_STORE_CTX *store_ctx, const char *descr)
> +{
> + X509*cert;
> + const STACK_OF(X509_EXTENSION)  *exts;
> + X509_EXTENSION  *ext;
> + ASN1_OBJECT *obj;
> + int  depth, error, i, nid;
> + int  saw_ipAddrBlock = 0;
> + int  saw_autonomousSysNum = 0;
> + int  saw_unknown = 0;
> +
> + error = X509_STORE_CTX_get_error(store_ctx);
> + depth = X509_STORE_CTX_get_error_depth(store_ctx);
> +
> + switch (error) {
> + case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
> + case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
> + break;
> + default:
> + return ok;
> + }
> +
> + fprintf(stderr, "%s cb: ok %d, %s, depth %d\n",
> + descr, ok, X509_verify_cert_error_string(error), depth);

Is there a reason you decided to use fprintf() over warnx() here?
And especially for the error cases below. AFAIK rpki-client uses warnx()
in almost all such cases.
Also we normally print the path of the file causing the error but I guess
this is tricky to pass in here. I guess one could use
X509_STORE_CTX_set_app_data() for that.

> + if ((cert = X509_STORE_CTX_get_current_cert(store_ctx)) == NULL) {
> + fprintf(stderr, "%s cb: got no current cert\n", descr);
> + return 0;
> + }
> + if ((exts = X509_get0_extensions(cert)) == NULL) {
> + fprintf(stderr, "%s cb: got no extensions\n", descr);
> + return 0;
> + }
> +
> + for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
> + ext = sk_X509_EXTENSION_value(exts, i);
> +
> + /* skip over non-critical and known extensions */
> + if (!X509_EXTENSION_get_critical(ext))
> + continue;
> + if (X509_supported_extension(ext))
> + continue;
> +
> + if ((obj = X509_EXTENSION_get_object(ext)) == NULL) {
> + fprintf(stderr, "%s cb: got no object\n", descr);
> +

simplify rpki-client entity marshal

2021-12-28 Thread Claudio Jeker
This re-shuffles struct entity a bit and removes the unneeded has_data
indicator. Both data and datasz are not null when data is present and null
when there is no data. With this in mind the code becomes simpler.

-- 
:wq Claudio

Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.99
diff -u -p -r1.99 extern.h
--- extern.h22 Dec 2021 09:35:14 -  1.99
+++ extern.h28 Dec 2021 15:40:55 -
@@ -336,13 +336,12 @@ enum publish_type {
  * and parsed.
  */
 struct entity {
-   enum rtype   type;  /* type of entity (not RTYPE_EOF) */
+   TAILQ_ENTRY(entity) entries;
char*file;  /* local path to file */
-   int  has_data;  /* whether data blob is specified */
unsigned char   *data;  /* optional data blob */
size_t   datasz;/* length of optional data blob */
int  talid; /* tal identifier */
-   TAILQ_ENTRY(entity) entries;
+   enum rtype   type;  /* type of entity (not RTYPE_EOF) */
 };
 TAILQ_HEAD(entityq, entity);
 
Index: main.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.169
diff -u -p -r1.169 main.c
--- main.c  22 Dec 2021 09:35:14 -  1.169
+++ main.c  28 Dec 2021 15:39:11 -
@@ -120,9 +120,7 @@ entity_read_req(struct ibuf *b, struct e
io_read_buf(b, >type, sizeof(ent->type));
io_read_buf(b, >talid, sizeof(ent->talid));
io_read_str(b, >file);
-   io_read_buf(b, >has_data, sizeof(ent->has_data));
-   if (ent->has_data)
-   io_read_buf_alloc(b, (void **)>data, >datasz);
+   io_read_buf_alloc(b, (void **)>data, >datasz);
 }
 
 /*
@@ -144,9 +142,7 @@ entity_write_req(const struct entity *en
io_simple_buffer(b, >type, sizeof(ent->type));
io_simple_buffer(b, >talid, sizeof(ent->talid));
io_str_buffer(b, ent->file);
-   io_simple_buffer(b, >has_data, sizeof(int));
-   if (ent->has_data)
-   io_buf_buffer(b, ent->data, ent->datasz);
+   io_buf_buffer(b, ent->data, ent->datasz);
io_close_buffer(, b);
 }
 
@@ -194,11 +190,8 @@ entityq_add(char *file, enum rtype type,
p->type = type;
p->talid = talid;
p->file = file;
-   p->has_data = data != NULL;
-   if (p->has_data) {
-   p->data = data;
-   p->datasz = datasz;
-   }
+   p->data = data;
+   p->datasz = (data != NULL) ? datasz : 0;
 
entity_queue++;
 
Index: parser.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.28
diff -u -p -r1.28 parser.c
--- parser.c4 Nov 2021 18:26:48 -   1.28
+++ parser.c28 Dec 2021 15:40:04 -
@@ -195,7 +195,7 @@ proc_parser_cert(const struct entity *en
STACK_OF(X509)  *chain;
STACK_OF(X509_CRL)  *crls;
 
-   assert(!entp->has_data);
+   assert(entp->data == NULL);
 
/* Extract certificate data and X509. */
 
@@ -274,7 +274,7 @@ proc_parser_root_cert(const struct entit
struct cert *cert;
X509*x509;
 
-   assert(entp->has_data);
+   assert(entp->data != NULL);
 
/* Extract certificate data and X509. */
 
@@ -525,7 +525,7 @@ parse_entity(struct entityq *q, struct m
tal_free(tal);
break;
case RTYPE_CER:
-   if (entp->has_data)
+   if (entp->data != NULL)
cert = proc_parser_root_cert(entp, f, flen);
else
cert = proc_parser_cert(entp, f, flen);



Re: rpki-client: check ipAddrBlock and autonomousSysNum for criticality

2021-12-29 Thread Claudio Jeker
On Wed, Dec 29, 2021 at 01:06:30AM +0100, Theo Buehler wrote:
> On Tue, Dec 28, 2021 at 05:08:46PM +0100, Claudio Jeker wrote:
> > On Mon, Dec 27, 2021 at 12:23:32PM +0100, Theo Buehler wrote:
> > > On Sat, Dec 25, 2021 at 05:48:53PM +0100, Claudio Jeker wrote:
> > > [...]
> > > > I would love to get rid of X509_V_FLAG_IGNORE_CRITICAL and use a 
> > > > callback
> > > > to ensure the right extensions are critical but I never managed to
> > > > understand how the X509_verify_cert() callback actually works.
> > > > Documentation seems to be non-existent.
> > > 
> > > My understanding is that X509_V_FLAG_IGNORE_CRITICAL is a big hammer
> > > that was necessary as long as libcrypto didn't know about the RFC 3779
> > > extensions. Without it X509_verify_cert() would error on encountering
> > > them. This changed shortly after Gouveia when we enabled the RFC 3779
> > > code in libcrypto. I think setting the flag is no longer appropriate in
> > > -current.
> > > 
> > > Below is a diff that removes X509_V_FLAG_IGNORE_CRITICAL and adds a
> > > debug verify callback that intercepts unhandled critical extensions. It
> > > lets through the RFC 3779 extensions and errors on everything else.
> > > 
> > > If you run with this on -current, the callback doesn't print anything.
> > > On -stable you'll see that it logs at least one of the two extensions
> > > per cert while X509_verify_cert() is walking through the chains.
> > > 
> > > If we want to drop X509_V_FLAG_IGNORE_CRITICAL, something like this
> > > will be needed as long as rpki-client wants to support LibreSSL < 3.5.
> > > The idea is that we handle RFC 3779 extensions ourselves, so we can
> > > safely ignore them in the verifier. All other critical extensions that
> > > neither rpki-client nor libcrypto know about should be verification
> > > failures.
> > > 
> > > You can play with this on -current by disabling RFC 3779 again: remove
> > > or comment the #ifndef LIBRESSL_CRYPTO_INTERNAL around OPENSSL_NO_RFC3779
> > > in lib/libcrypto/opensslfeatures.h then make clean, make includes, make
> > > and make install.
> > 
> > I like this. A few questions inline.
> 
> cool
> 
> > > + fprintf(stderr, "%s cb: ok %d, %s, depth %d\n",
> > > + descr, ok, X509_verify_cert_error_string(error), depth);
> > 
> > Is there a reason you decided to use fprintf() over warnx() here?
> 
> Only that I didn't really intend this for commit and was therefore a bit
> lazy. I should have made that clearer.
> 
> > And especially for the error cases below. AFAIK rpki-client uses warnx()
> > in almost all such cases.
> > Also we normally print the path of the file causing the error but I guess
> > this is tricky to pass in here. I guess one could use
> > X509_STORE_CTX_set_app_data() for that.
> 
> Good idea, yes, that works.
> 
> > > +static int
> > > +roa_verify_cb(int ok, X509_STORE_CTX *store_ctx)
> > > +{
> > > + return generic_verify(ok, store_ctx, "roa");
> > > +}
> > 
> > Is there no other way to avoid this extra wrapping of functions?
> 
> It was the first thing that came to mind so I could tell where the calls
> originated.
> 
> > See above I guess using X509_STORE_CTX_set_app_data() and
> > X509_STORE_CTX_get_app_data() these wrappers become unnecessary.
> 
> I think the suffix of the file gives enough of a clue, so that's
> definitely no longer needed.

Absolutly. Idealy we can pass the path to rpki-client -f in the future to
get a verbose output of the object in question.
 
> This should be closer to commit now. I removed the switch over the error
> since I guess we would need to handle unhandled critical CRL extensions
> differently.  I switched the fprintf to warnx, although some more of
> them should perhaps be fatal since it's most likely an allocation
> failure.

Not too worried about those errors, I doubt the will be seen often.
Lets decide if someone actually runs into those.
 
> Since this is super noisy (multiple lines per processed file), I reduced
> to printing one line in the ordinary path and only on verbosity > 1. We
> might even want to crank that higher or ditch this last warnx altogether.

I think the verbose > 1 warnx could indeed be removed. With modern libs it
will be never hit and for old libs the code takes care of this.
Would simplify the code a bit more.
 
> I also suppressed printing the cert error and the ok variable since I
> don't think this is actually interesting, 

Re: fix vmctl -B net -b bsd.rd to autoinstall

2021-12-29 Thread Claudio Jeker
On Wed, Dec 22, 2021 at 12:34:34PM -0500, Dave Voutila wrote:
> 
> Claudio Jeker  writes:
> 
> > On Wed, Dec 22, 2021 at 10:14:40AM -0500, Dave Voutila wrote:
> >>
> >> Claudio Jeker  writes:
> >>
> >> > I added support for vmctl -cL -B net -b bsd.rd -d disk.img to run the
> >> > autoinstall by emulating a PXE boot. In the commit
> >> > https://github.com/openbsd/src/commit/a13de4d12a4c9ba0edc05aab2ad635f782449229
> >> > the feature got removed over eagerly.
> >> >
> >> > This diff adds this back because I find this super practical.
> >>
> >> Seems to add back more than that...see below.
> >>
> >
> > Those are becasue of warnings from the compiler and I do not like to send
> > out diffs for files that compile with a bunch of warnings.
> > I can split this out into an extra commit if people prefer that.
> >
> 
> Yes please. :) Understand the warnings concern, though.
> 

So here is the diff just fixing -B net -b bsd.rd
Somebody else can look into all the clang 13 errors in vmd.

-- 
:wq Claudio

Index: loadfile.h
===
RCS file: /cvs/src/usr.sbin/vmd/loadfile.h,v
retrieving revision 1.15
diff -u -p -r1.15 loadfile.h
--- loadfile.h  16 Jun 2021 16:55:02 -  1.15
+++ loadfile.h  22 Dec 2021 14:34:06 -
@@ -80,7 +80,8 @@
 #define PML2_PAGE 0x13000
 #define NPTE_PG (PAGE_SIZE / sizeof(uint64_t))
 
-int loadfile_elf(gzFile, struct vm_create_params *, struct vcpu_reg_state *);
+intloadfile_elf(gzFile, struct vm_create_params *, struct vcpu_reg_state *,
+   unsigned int);
 
 size_t mread(gzFile, paddr_t, size_t);
 
Index: loadfile_elf.c
===
RCS file: /cvs/src/usr.sbin/vmd/loadfile_elf.c,v
retrieving revision 1.39
diff -u -p -r1.39 loadfile_elf.c
--- loadfile_elf.c  4 May 2021 10:48:51 -   1.39
+++ loadfile_elf.c  29 Dec 2021 13:14:04 -
@@ -118,7 +118,7 @@ static void setsegment(struct mem_segmen
 static int elf32_exec(gzFile, Elf32_Ehdr *, u_long *, int);
 static int elf64_exec(gzFile, Elf64_Ehdr *, u_long *, int);
 static size_t create_bios_memmap(struct vm_create_params *, bios_memmap_t *);
-static uint32_t push_bootargs(bios_memmap_t *, size_t);
+static uint32_t push_bootargs(bios_memmap_t *, size_t, bios_bootmac_t *);
 static size_t push_stack(uint32_t, uint32_t);
 static void push_gdt(void);
 static void push_pt_32(void);
@@ -264,13 +264,14 @@ push_pt_64(void)
  */
 int
 loadfile_elf(gzFile fp, struct vm_create_params *vcp,
-struct vcpu_reg_state *vrs)
+struct vcpu_reg_state *vrs, unsigned int bootdevice)
 {
int r, is_i386 = 0;
uint32_t bootargsz;
size_t n, stacksize;
u_long marks[MARK_MAX];
bios_memmap_t memmap[VMM_MAX_MEM_RANGES + 1];
+   bios_bootmac_t bm, *bootmac = NULL;
 
if ((r = gzread(fp, , sizeof(hdr))) != sizeof(hdr))
return 1;
@@ -301,8 +302,12 @@ loadfile_elf(gzFile fp, struct vm_create
else
push_pt_64();
 
+   if (bootdevice & VMBOOTDEV_NET) {
+   bootmac = 
+   memcpy(bootmac, vcp->vcp_macs[0], ETHER_ADDR_LEN);
+   }
n = create_bios_memmap(vcp, memmap);
-   bootargsz = push_bootargs(memmap, n);
+   bootargsz = push_bootargs(memmap, n, bootmac);
stacksize = push_stack(bootargsz, marks[MARK_END]);
 
vrs->vrs_gprs[VCPU_REGS_RIP] = (uint64_t)marks[MARK_ENTRY];
@@ -382,9 +387,9 @@ create_bios_memmap(struct vm_create_para
  *  The size of the bootargs
  */
 static uint32_t
-push_bootargs(bios_memmap_t *memmap, size_t n)
+push_bootargs(bios_memmap_t *memmap, size_t n, bios_bootmac_t *bootmac)
 {
-   uint32_t memmap_sz, consdev_sz, i;
+   uint32_t memmap_sz, consdev_sz, bootmac_sz, i;
bios_consdev_t consdev;
uint32_t ba[1024];
 
@@ -407,6 +412,15 @@ push_bootargs(bios_memmap_t *memmap, siz
ba[i + 2] = consdev_sz;
memcpy([i + 3], , sizeof(bios_consdev_t));
i += consdev_sz / sizeof(int);
+
+   if (bootmac) {
+   bootmac_sz = 3 * sizeof(int) + (sizeof(bios_bootmac_t) + 3) & 
~3;
+   ba[i] = 0x7;   /* bootmac */
+   ba[i + 1] = bootmac_sz;
+   ba[i + 2] = bootmac_sz;
+   memcpy([i + 3], bootmac, sizeof(bios_bootmac_t));
+   i += bootmac_sz / sizeof(int);
+   } 
 
ba[i++] = 0x; /* BOOTARG_END */
 
Index: vm.c
===
RCS file: /cvs/src/usr.sbin/vmd/vm.c,v
retrieving revision 1.66
diff -u -p -r1.66 vm.c
--- vm.c29 Nov 2021 05:17:35 -  1.66
+++ vm.c22 Dec 2021 14:33:55 -
@@ -336,7 +336,7 @@ start_vm(struct vmd_vm *vm, int fd)
fat

fix some -Wunused-but-set-variable warnings in vmd

2022-01-04 Thread Claudio Jeker
This are obvious and easy to fix unused but set variables.
There are more in vioscsi.c but those are actually used if compiled with
DEBUG set.

-- 
:wq Claudio

Index: loadfile_elf.c
===
RCS file: /cvs/src/usr.sbin/vmd/loadfile_elf.c,v
retrieving revision 1.40
diff -u -p -r1.40 loadfile_elf.c
--- loadfile_elf.c  30 Dec 2021 08:12:23 -  1.40
+++ loadfile_elf.c  4 Jan 2022 09:46:07 -
@@ -499,7 +499,7 @@ mread(gzFile fp, paddr_t addr, size_t sz
const char *errstr = NULL;
int errnum = 0;
size_t ct;
-   size_t i, rd, osz;
+   size_t i, osz;
char buf[PAGE_SIZE];
 
/*
@@ -507,7 +507,6 @@ mread(gzFile fp, paddr_t addr, size_t sz
 * write_mem
 */
ct = 0;
-   rd = 0;
osz = sz;
if ((addr & PAGE_MASK) != 0) {
memset(buf, 0, sizeof(buf));
@@ -524,7 +523,6 @@ mread(gzFile fp, paddr_t addr, size_t sz
errnum, errstr);
return (0);
}
-   rd += ct;
 
if (write_mem(addr, buf, ct))
return (0);
@@ -552,7 +550,6 @@ mread(gzFile fp, paddr_t addr, size_t sz
errnum, errstr);
return (0);
}
-   rd += ct;
 
if (write_mem(addr, buf, ct))
return (0);
@@ -678,7 +675,6 @@ elf64_exec(gzFile fp, Elf64_Ehdr *elf, u
Elf64_Off off;
int i;
size_t sz;
-   int first;
int havesyms;
paddr_t minp = ~0, maxp = 0, pos = 0;
paddr_t offset = marks[MARK_START], shpp, elfp;
@@ -696,7 +692,7 @@ elf64_exec(gzFile fp, Elf64_Ehdr *elf, u
return 1;
}
 
-   for (first = 1, i = 0; i < elf->e_phnum; i++) {
+   for (i = 0; i < elf->e_phnum; i++) {
if (phdr[i].p_type == PT_OPENBSD_RANDOMIZE) {
int m;
 
@@ -741,8 +737,6 @@ elf64_exec(gzFile fp, Elf64_Ehdr *elf, u
free(phdr);
return 1;
}
-
-   first = 0;
}
 
if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT | COUNT_TEXT))) ||
@@ -816,7 +810,7 @@ elf64_exec(gzFile fp, Elf64_Ehdr *elf, u
if (shp[i].sh_type == SHT_SYMTAB)
havesyms = 1;
 
-   for (first = 1, i = 0; i < elf->e_shnum; i++) {
+   for (i = 0; i < elf->e_shnum; i++) {
if (shp[i].sh_type == SHT_SYMTAB ||
shp[i].sh_type == SHT_STRTAB ||
!strcmp(shstr + shp[i].sh_name, ".debug_line") ||
@@ -841,7 +835,6 @@ elf64_exec(gzFile fp, Elf64_Ehdr *elf, u
shp[i].sh_flags |= SHF_ALLOC;
off += roundup(shp[i].sh_size,
sizeof(Elf64_Addr));
-   first = 0;
}
}
if (flags & LOAD_SYM) {
@@ -900,7 +893,6 @@ elf32_exec(gzFile fp, Elf32_Ehdr *elf, u
Elf32_Off off;
int i;
size_t sz;
-   int first;
int havesyms;
paddr_t minp = ~0, maxp = 0, pos = 0;
paddr_t offset = marks[MARK_START], shpp, elfp;
@@ -918,7 +910,7 @@ elf32_exec(gzFile fp, Elf32_Ehdr *elf, u
return 1;
}
 
-   for (first = 1, i = 0; i < elf->e_phnum; i++) {
+   for (i = 0; i < elf->e_phnum; i++) {
if (phdr[i].p_type == PT_OPENBSD_RANDOMIZE) {
int m;
 
@@ -963,8 +955,6 @@ elf32_exec(gzFile fp, Elf32_Ehdr *elf, u
free(phdr);
return 1;
}
-
-   first = 0;
}
 
if ((IS_TEXT(phdr[i]) && (flags & (LOAD_TEXT | COUNT_TEXT))) ||
@@ -1038,7 +1028,7 @@ elf32_exec(gzFile fp, Elf32_Ehdr *elf, u
if (shp[i].sh_type == SHT_SYMTAB)
havesyms = 1;
 
-   for (first = 1, i = 0; i < elf->e_shnum; i++) {
+   for (i = 0; i < elf->e_shnum; i++) {
if (shp[i].sh_type == SHT_SYMTAB ||
shp[i].sh_type == SHT_STRTAB ||
!strcmp(shstr + shp[i].sh_name, ".debug_line")) {
@@ -1062,7 +1052,6 @@ elf32_exec(gzFile fp, Elf32_Ehdr *elf, u
shp[i].sh_flags |= SHF_ALLOC;
off += roundup(shp[i].sh_size,
sizeof(Elf32_Addr));
-   first = 0;
}
}
if (flags & LOAD_SYM) {
Index: vioqcow2.c
===
RCS 

Re: uhidppctl(8)

2021-12-22 Thread Claudio Jeker
On Tue, Dec 21, 2021 at 03:49:47PM -0500, jwinnie@tilde.institute wrote:
> 
> Hello OpenBSD developers,
> 
> I am interested in contributing to improve the uhidpp(4)
> (Logitech Unifying Reciever) support in OpenBSD.
> 
> Currently, the uhidpp(4) driver only handles detecting certain
> sensors, but I would like more robust support for these devices,
> including:
> 
> * pairing and unpairing devices on the command-line
> * controlling the scrolling speed/auxiliary buttons of wireless mice
> 
> Do you know where I should start? Should I work on the uhidpp(4)
> driver, or should I go ahead and start writing a command-line utility,
> like uhidppctl(8)?

I doubt we want a uhidppctl(8) unless it is really necessary.
I would expect wsmouse(4) to handle the controlling of scrolling
speed and auxiliary buttons.

-- 
:wq Claudio



Re: rpki-client, stop using size_t for ids

2021-12-22 Thread Claudio Jeker
On Tue, Dec 21, 2021 at 06:24:44PM +, Job Snijders wrote:
> On Tue, Dec 21, 2021 at 07:00:03PM +0100, Claudio Jeker wrote:
> > For some reasons various ids were stored as size_t (probably because once
> > they used to be the index in an array). This is just silly and annoyed me
> > for long enough. I think this fixes all of them.
> > 
> > While there also stop using size_t for maxlength of a prefix. Everywhere
> > else the code uses just a unsigned char for that so do it there as well.
> > Shuffle struct a little bit in hope for better packing.
> > 
> > Seems to work with RRDP and RSYNC.
> 
> print.c line 155 may need a small change too (-Wformat error)

Cool, I changed that %zu to %hhu.
 
> other than that, OK job@

Thanks.

-- 
:wq Claudio



Re: sppp(4)/pppoe(4) - DNS configuration via resolvd(8)

2021-11-10 Thread Claudio Jeker
On Wed, Nov 10, 2021 at 07:35:26AM +0100, Bjorn Ketelaars wrote:
> On Mon 08/11/2021 11:52, Bjorn Ketelaars wrote:
> > Diff below does two things:
> > 1. add PPP IPCP extensions for name server addresses (rfc1877) to
> >sppp(4)
> > 2. propose negotiated name servers from sppp(4) to resolvd(8) using
> >RTM_PROPOSAL_STATIC route messages.
> 
> 
> Updated diff below, based on feedback from kn@ and claudio@:
> 
> - fix forgotten parentheses with `sizeof`
> - instead of using `u_int32_t` use `struct in_addr` for holding dns
>   addresses. Makes it more clear what the data is
> - decouple `IPCP_OPT` definitions from the bitmask values to
>   enable/disable an option. Makes the code look a bit better
> - use `memcpy`
> - fit code within 80 columns
> 
> While here add RFC to sppp(4)'s STANDARDS section.
> 
> @kn, is this still OK for you?
> 
> Other OK's?
> 
> 
> diff --git share/man/man4/sppp.4 share/man/man4/sppp.4
> index 5ca10285953..bccb41eec15 100644
> --- share/man/man4/sppp.4
> +++ share/man/man4/sppp.4
> @@ -230,6 +230,13 @@ take place.
>  .Re
>  .Pp
>  .Rs
> +.%A S. Cobb
> +.%D December 1995
> +.%R RFC 1877
> +.%T PPP Internet Protocol Control Protocol Extensions for Name Server 
> Addresses
> +.Re
> +.Pp
> +.Rs
>  .%A W. Simpson
>  .%D August 1996
>  .%R RFC 1994
> diff --git sys/net/if_sppp.h sys/net/if_sppp.h
> index ff559fcc369..5850a6da963 100644
> --- sys/net/if_sppp.h
> +++ sys/net/if_sppp.h
> @@ -132,6 +132,8 @@ struct sipcp {
> * original one here, in network byte order */
>   u_int32_t req_hisaddr;  /* remote address requested (IPv4) */
>   u_int32_t req_myaddr;   /* local address requested (IPv4) */
> +#define IPCP_MAX_DNSSRV  2
> + struct in_addr dns[IPCP_MAX_DNSSRV]; /* IPv4  DNS servers (RFC 1877) */
>  #ifdef INET6
>   struct in6_aliasreq req_ifid;   /* local ifid requested (IPv6) */
>  #endif
> diff --git sys/net/if_spppsubr.c sys/net/if_spppsubr.c
> index ac1dc9a709d..e460703c089 100644
> --- sys/net/if_spppsubr.c
> +++ sys/net/if_spppsubr.c
> @@ -132,6 +132,14 @@
>  #define IPCP_OPT_ADDRESSES   1   /* both IP addresses; deprecated */
>  #define IPCP_OPT_COMPRESSION 2   /* IP compression protocol (VJ) */
>  #define IPCP_OPT_ADDRESS 3   /* local IP address */
> +#define IPCP_OPT_PRIMDNS 129 /* primary remote dns address */
> +#define IPCP_OPT_SECDNS  131 /* secondary remote dns address 
> */
> +
> +#define SPPP_IPCP_OPT_ADDRESSES  1   /* bitmask value */
> +#define SPPP_IPCP_OPT_COMPRESSION2   /* bitmask value */
> +#define SPPP_IPCP_OPT_ADDRESS3   /* bitmask value */
> +#define SPPP_IPCP_OPT_PRIMDNS4   /* bitmask value */
> +#define SPPP_IPCP_OPT_SECDNS 5   /* bitmask value */

Instead of repeating the /* bitmask value */ just add a comment at the
top. Something like "bitmask value to enable or disable individual IPCP
options"

>  
>  #define IPV6CP_OPT_IFID  1   /* interface identifier */
>  #define IPV6CP_OPT_COMPRESSION   2   /* IPv6 compression protocol */
> @@ -338,6 +346,8 @@ void sppp_update_gw(struct ifnet *ifp);
>  void sppp_set_ip_addrs(void *);
>  void sppp_clear_ip_addrs(void *);
>  void sppp_set_phase(struct sppp *sp);
> +void sppp_update_dns(struct ifnet *ifp);
> +void sppp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt);
>  
>  /* our control protocol descriptors */
>  static const struct cp lcp = {
> @@ -701,6 +711,7 @@ sppp_attach(struct ifnet *ifp)
>  
>   sp->pp_if.if_type = IFT_PPP;
>   sp->pp_if.if_output = sppp_output;
> + sp->pp_if.if_rtrequest = sppp_rtrequest;
>   ifq_set_maxlen(>pp_if.if_snd, 50);
>   mq_init(>pp_cpq, 50, IPL_NET);
>   sp->pp_loopcnt = 0;
> @@ -2512,13 +2523,19 @@ sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header 
> *h, int len)
>* Peer doesn't grok address option.  This is
>* bad.  XXX  Should we better give up here?
>*/
> - sp->ipcp.opts &= ~(1 << IPCP_OPT_ADDRESS);
> + sp->ipcp.opts &= ~(1 << SPPP_IPCP_OPT_ADDRESS);
>   break;
>  #ifdef notyet
>   case IPCP_OPT_COMPRESS:
> - sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS);
> + sp->ipcp.opts &= ~(1 << SPPP_IPCP_OPT_COMPRESS);
>   break;
>  #endif
> + case IPCP_OPT_PRIMDNS:
> + sp->ipcp.opts &= ~(1 << SPPP_IPCP_OPT_PRIMDNS);
> + break;
> + case IPCP_OPT_SECDNS:
> + sp->ipcp.opts &= ~(1 << SPPP_IPCP_OPT_SECDNS);
> + break;
>   }
>   }
>   if (debug)
> @@ -2559,7 +2576,7 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header 
> *h, int len)
>   if (len >= 6 && p[1] == 6) {
>   wantaddr = p[2] << 24 

Re: sppp(4)/pppoe(4) - DNS configuration via resolvd(8)

2021-11-10 Thread Claudio Jeker
On Wed, Nov 10, 2021 at 08:22:52AM +0100, Sebastien Marie wrote:
> On Wed, Nov 10, 2021 at 07:35:26AM +0100, Bjorn Ketelaars wrote:
> > On Mon 08/11/2021 11:52, Bjorn Ketelaars wrote:
> > > Diff below does two things:
> > > 1. add PPP IPCP extensions for name server addresses (rfc1877) to
> > >sppp(4)
> > > 2. propose negotiated name servers from sppp(4) to resolvd(8) using
> > >RTM_PROPOSAL_STATIC route messages.
> > 
> > 
> > Updated diff below, based on feedback from kn@ and claudio@:
> > 
> > - fix forgotten parentheses with `sizeof`
> > - instead of using `u_int32_t` use `struct in_addr` for holding dns
> >   addresses. Makes it more clear what the data is
> > - decouple `IPCP_OPT` definitions from the bitmask values to
> >   enable/disable an option. Makes the code look a bit better
> > - use `memcpy`
> > - fit code within 80 columns
> > 
> > While here add RFC to sppp(4)'s STANDARDS section.
> > 
> > @kn, is this still OK for you?
> > 
> > Other OK's?
> 
> There is one point which bother me a bit: you are using
> RTP_PROPOSAL_STATIC for sending the proposal, whereas all others
> sources (dhcpleased/dhclient, slaacd, umb) are using a specific value.
> 
> By using RTP_PROPOSAL_STATIC, it means also that route(8) nameserver
> subcommand might interfere with it.
> 
> Using a new specific value (like RTP_PROPOSAL_SPPP) would make sense
> to me. But no objection if RTM_PROPOSAL_STATIC is preferred.

Agreed, This should use its own prio. I would suggest to call it
RTP_PROPOSAL_PPP. This is something that can be done independently.

-- 
:wq Claudio



Re: sigsuspend(2): sleep on channel?

2021-11-11 Thread Claudio Jeker
On Thu, Nov 11, 2021 at 02:13:26PM -0600, Scott Cheloha wrote:
> On Thu, Nov 11, 2021 at 08:53:20PM +0100, Mark Kettenis wrote:
> > > Date: Thu, 11 Nov 2021 13:30:04 -0600
> > > From: Scott Cheloha 
> > > 
> > > My understanding of sigsuspend(2) is that it only returns if a signal
> > > is delivered to the calling thread.  However, in sys_sigsuspend() we
> > > pass >p_p->ps_sigacts as the wakeup channel to tsleep_nsec(9).
> > > 
> > > Are we actually waiting for a wakeup on that channel?  Or can we sleep
> > > on  here?  Patch attached.  Note that we don't need to loop
> > > here anymore: we can't receieve wakeup so tsleep_nsec(9) will never
> > > return zero.
> > 
> > I don't think we expect a wakeup on that channel.  But the loop is
> > still needed as a spurious wakeup may happen.
> 
> I'm not quite sure how you'd get a spurious wakeup in this context,
> but I'll take your word for it.
> 
> So use  to indicate we're not expecting a wakeup, but keep the
> loop.
> 
> Index: kern_sig.c
> ===
> RCS file: /cvs/src/sys/kern/kern_sig.c,v
> retrieving revision 1.287
> diff -u -p -r1.287 kern_sig.c
> --- kern_sig.c24 Oct 2021 00:02:25 -  1.287
> +++ kern_sig.c11 Nov 2021 20:10:51 -
> @@ -509,7 +509,7 @@ dosigsuspend(struct proc *p, sigset_t ne
>  }
>  
>  /*
> - * Suspend process until signal, providing mask to be set
> + * Suspend thread until signal, providing mask to be set
>   * in the meantime.  Note nonstandard calling convention:
>   * libc stub passes mask, not pointer, to save a copyin.
>   */
> @@ -519,12 +519,10 @@ sys_sigsuspend(struct proc *p, void *v, 
>   struct sys_sigsuspend_args /* {
>   syscallarg(int) mask;
>   } */ *uap = v;
> - struct process *pr = p->p_p;
> - struct sigacts *ps = pr->ps_sigacts;
>  
>   dosigsuspend(p, SCARG(uap, mask) &~ sigcantmask);
> - while (tsleep_nsec(ps, PPAUSE|PCATCH, "sigsusp", INFSLP) == 0)
> - /* void */;
> + while (tsleep_nsec(, PPAUSE|PCATCH, "sigsusp", INFSLP) == 0)
> + continue;
>   /* always return EINTR rather than ERESTART... */
>   return (EINTR);
>  }
> 

OK claudio@
-- 
:wq Claudio



support probe as variable in btrace

2021-11-12 Thread Claudio Jeker
This is something I missed to do easy btrace check like:
syscall:exit:entry,
syscall:fork:entry,
syscall:sigaction:entry,
syscall:execve:entry,
syscall:open:entry { @[probe] = count(); }

This will produce something like this as output:
@[syscall:open:entry]: 844
@[syscall:sigaction:entry]: 480
@[syscall:execve:entry]: 27
@[syscall:exit:entry]: 26
@[syscall:fork:entry]: 24

Works for me. I decided to qsort the dt_dtpis array so that bsearch can be
used for quick lookups by id. If the kernel ensures that the returned
array from the ioctl is always sorted this could be skipped.

-- 
:wq Claudio


Index: bt.5
===
RCS file: /cvs/src/usr.sbin/btrace/bt.5,v
retrieving revision 1.12
diff -u -p -r1.12 bt.5
--- bt.53 Oct 2021 22:01:48 -   1.12
+++ bt.512 Nov 2021 14:05:16 -
@@ -105,6 +105,8 @@ Kernel stack of the current thread.
 Timestamp of the event in nanoseconds.
 .It Va pid
 Process ID of the current thread.
+.It Va probe
+Full name of the probe.
 .It Va retval
 Return value of the traced syscall.
 .It Va tid
Index: bt_parse.y
===
RCS file: /cvs/src/usr.sbin/btrace/bt_parse.y,v
retrieving revision 1.44
diff -u -p -r1.44 bt_parse.y
--- bt_parse.y  3 Oct 2021 22:01:48 -   1.44
+++ bt_parse.y  12 Nov 2021 13:46:22 -
@@ -717,6 +717,7 @@ lookup(char *s)
{ "pid",BUILTIN,B_AT_BI_PID },
{ "print",  F_PRINT,B_AC_PRINT },
{ "printf", FUNCN,  B_AC_PRINTF },
+   { "probe",  BUILTIN,B_AT_BI_PROBE },
{ "retval", BUILTIN,B_AT_BI_RETVAL },
{ "str",STR,B_AT_FN_STR },
{ "sum",MOP1,   B_AT_MF_SUM },
Index: bt_parser.h
===
RCS file: /cvs/src/usr.sbin/btrace/bt_parser.h,v
retrieving revision 1.21
diff -u -p -r1.21 bt_parser.h
--- bt_parser.h 3 Oct 2021 22:01:48 -   1.21
+++ bt_parser.h 12 Nov 2021 13:12:43 -
@@ -147,6 +147,7 @@ struct bt_arg {
B_AT_BI_ARG9,
B_AT_BI_ARGS,
B_AT_BI_RETVAL,
+   B_AT_BI_PROBE,
 
B_AT_FN_STR,/* str($1); str($1, 3); */
 
Index: btrace.c
===
RCS file: /cvs/src/usr.sbin/btrace/btrace.c,v
retrieving revision 1.59
diff -u -p -r1.59 btrace.c
--- btrace.c24 Oct 2021 14:18:58 -  1.59
+++ btrace.c12 Nov 2021 13:55:52 -
@@ -256,6 +256,18 @@ read_btfile(const char *filename, size_t
return fcontent;
 }
 
+static int
+dtpi_cmp(const void *a, const void *b)
+{
+   const struct dtioc_probe_info *ai = a, *bi = b;
+
+   if (ai->dtpi_pbn > bi->dtpi_pbn)
+   return 1;
+   if (ai->dtpi_pbn < bi->dtpi_pbn)
+   return -1;
+   return 0;
+}
+
 void
 dtpi_cache(int fd)
 {
@@ -276,6 +288,8 @@ dtpi_cache(int fd)
dtpr.dtpr_probes = dt_dtpis;
if (ioctl(fd, DTIOCGPLIST, ))
err(1, "DTIOCGPLIST");
+
+   qsort(dt_dtpis, dt_ndtpi, sizeof(*dt_dtpis), dtpi_cmp);
 }
 
 void
@@ -351,6 +365,15 @@ dtpi_get_by_value(const char *prov, cons
return NULL;
 }
 
+static struct dtioc_probe_info *
+dtpi_get_by_id(unsigned int pbn)
+{
+   struct dtioc_probe_info d;
+
+   d.dtpi_pbn = pbn;
+   return bsearch(, dt_dtpis, dt_ndtpi, sizeof(*dt_dtpis), dtpi_cmp);
+}
+
 void
 rules_do(int fd)
 {
@@ -1263,6 +1286,8 @@ ba_name(struct bt_arg *ba)
return "args";
case B_AT_BI_RETVAL:
return "retval";
+   case B_AT_BI_PROBE:
+   return "probe";
case B_AT_FN_STR:
return "str";
case B_AT_OP_PLUS:
@@ -1372,6 +1397,9 @@ ba2long(struct bt_arg *ba, struct dt_evt
case B_AT_BI_RETVAL:
val = dtev->dtev_retval[0];
break;
+   case B_AT_BI_PROBE:
+   val = dtev->dtev_pbn;
+   break;
case B_AT_OP_PLUS ... B_AT_OP_LOR:
val = baexpr2long(ba, dtev);
break;
@@ -1390,6 +1418,7 @@ ba2str(struct bt_arg *ba, struct dt_evt 
 {
static char buf[STRLEN];
struct bt_var *bv;
+   struct dtioc_probe_info *dtpi;
const char *str;
 
buf[0] = '\0';
@@ -1436,6 +1465,15 @@ ba2str(struct bt_arg *ba, struct dt_evt 
snprintf(buf, sizeof(buf), "%ld", (long)dtev->dtev_retval[0]);
str = buf;
break;
+   case B_AT_BI_PROBE:
+   dtpi = dtpi_get_by_id(dtev->dtev_pbn);
+   if (dtpi != NULL)
+   snprintf(buf, sizeof(buf), "%s:%s:%s",
+   dtpi->dtpi_prov, dtpi_func(dtpi), dtpi->dtpi_name);
+   else
+   

bt.5 document count()

2021-11-16 Thread Claudio Jeker
This documents count(). This function only works when used like this
@map[key] = count();
But it is implemented and works. If used differently you get a syntax
error which is not helpful. This is why I chose to document it like this.
Another option would be to document the language (so it is clear where it
is possible to use what). 

max(), min() and sum() are other functions that behave like this. Their
documentation should also be adjusted IMO.

-- 
:wq Claudio

Index: bt.5
===
RCS file: /cvs/src/usr.sbin/btrace/bt.5,v
retrieving revision 1.13
diff -u -p -r1.13 bt.5
--- bt.512 Nov 2021 16:57:24 -  1.13
+++ bt.516 Nov 2021 09:50:52 -
@@ -120,6 +120,11 @@ Functions:
 .It Fn clear "@map"
 Delete all (key, value) pairs from
 .Va @map .
+.It "@map[key]" = Fn count
+Increment the value of
+.Va key
+from
+.Va @map .
 .It Fn delete "@map[key]"
 Delete the pair indexed by
 .Va key



rpki-client code shuffle

2021-11-24 Thread Claudio Jeker
4 Nov 2021 12:52:56 -
@@ -35,14 +35,22 @@ enum rrdp_task {
DELTA,
 };
 
-/* rrdp generic */
-char   *xstrdup(const char *);
-int hex_decode(const char *, char *, size_t);
-
-/* publish or withdraw element */
 struct rrdp;
-struct publish_xml;
 
+struct publish_xml {
+   char*uri;
+   char*data;
+   char hash[SHA256_DIGEST_LENGTH];
+   size_t   data_length;
+   enum publish_typetype;
+};
+
+/* rrdp generic */
+char   *xstrdup(const char *);
+voidrrdp_publish_file(struct rrdp *, struct publish_xml *,
+   unsigned char *, size_t);
+
+/* rrdp util */
 struct publish_xml *new_publish_xml(enum publish_type, char *,
char *, size_t);
 voidfree_publish_xml(struct publish_xml *);
Index: rrdp_notification.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/rrdp_notification.c,v
retrieving revision 1.11
diff -u -p -r1.11 rrdp_notification.c
--- rrdp_notification.c 9 Nov 2021 11:01:04 -   1.11
+++ rrdp_notification.c 24 Nov 2021 13:26:02 -
@@ -464,6 +464,19 @@ notification_delta_done(struct notificat
 void
 log_notification_xml(struct notification_xml *nxml)
 {
+   struct delta_item *d;
+   char *hash;
+
logx("session_id: %s, serial: %lld", nxml->session_id, nxml->serial);
logx("snapshot_uri: %s", nxml->snapshot_uri);
+   hash = hex_encode(nxml->snapshot_hash, sizeof(nxml->snapshot_hash));
+   logx("snapshot hash: %s", hash);
+   free(hash);
+
+   TAILQ_FOREACH(d, >delta_q, q) {
+   logx("delta serial %lld uri: %s", d->serial, d->uri);
+   hash = hex_encode(d->hash, sizeof(d->hash));
+   logx("delta hash: %s", hash);
+   free(hash);
+   }
 }
Index: rrdp_util.c
=======
RCS file: rrdp_util.c
diff -N rrdp_util.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ rrdp_util.c 24 Nov 2021 12:50:03 -
@@ -0,0 +1,120 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Nils Fisher 
+ * Copyright (c) 2021 Claudio Jeker 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "extern.h"
+#include "rrdp.h"
+
+/*
+ * Both snapshots and deltas use publish_xml to store the publish and
+ * withdraw records. Once all the content is added the request is sent
+ * to the main process where it is processed.
+ */
+struct publish_xml *
+new_publish_xml(enum publish_type type, char *uri, char *hash, size_t hlen)
+{
+   struct publish_xml *pxml;
+
+   if ((pxml = calloc(1, sizeof(*pxml))) == NULL)
+   err(1, "%s", __func__);
+
+   pxml->type = type;
+   pxml->uri = uri;
+   if (hlen > 0) {
+   assert(hlen == sizeof(pxml->hash));
+   memcpy(pxml->hash, hash, hlen);
+   }
+
+   return pxml;
+}
+
+void
+free_publish_xml(struct publish_xml *pxml)
+{
+   if (pxml == NULL)
+   return;
+
+   free(pxml->uri);
+   free(pxml->data);
+   free(pxml);
+}
+
+/*
+ * Add buf to the base64 data string, ensure that this remains a proper
+ * string by NUL-terminating the string.
+ */
+int
+publish_add_content(struct publish_xml *pxml, const char *buf, int length)
+{
+   size_t newlen, outlen;
+
+   /*
+* optmisiation, this often gets called with '\n' as the
+* only data... seems wasteful
+*/
+   if (length == 1 && buf[0] == '\n')
+   return 0;
+
+   /* append content to data */
+   if (SIZE_MAX - length - 1 <= pxml->data_length)
+   return -1;
+   newlen = pxml->data_length + length;
+   if (base64_decode_len(newlen, ) == -1 ||
+   outlen > MAX_FILE_SIZE)
+   return -1;
+
+   pxml->data = realloc(pxml->data, newlen + 1);
+   if (pxml->data == NULL)
+   err(1, "%s", __func__);
+
+   memcpy(p

Re: [External] : Re: make 'set skip on ...' dynamic

2021-11-26 Thread Claudio Jeker
On Thu, Nov 25, 2021 at 02:56:02PM +0100, Alexandr Nedvedicky wrote:
> Hello,
> 
> thank you for taking a look at my diff.
> 
> 
> 
> > >   }
> > >  
> > > - if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all)
> > > + if (kif->pfik_ifp != NULL || kif->pfik_group != NULL ||kif == pfi_all)
> > 
> > Missing space over^^^ here
> 
> fixed, looks like unintended change
> > > + if (found == 0) {
> > > + if (name == NULL)
> > > + return (0);
> > > +
> > > + n = strlen(name);
> > > + if ((n < 1) || (n >= IFNAMSIZ))
> > I would just use:
> > if (n < 1 || n >= IFNAMSIZ)
> > like in other places.
> 
> sure.
> 
> > 
> > > + return (0);
> > > +
> > > + if (((name[0] < 'a') || (name[0] > 'z')) ||
> > > + ((name[0] < 'A') && (name[0] > 'Z')))
> > > + return (0);
> > 
> > Not sure what you're after here. The logic of this construct is incorrect.
> > I would steal the defines from libsa/stand.h and then us !isalpha:
> > 
> > #define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
> > #define islower(c)  ((c) >= 'a' && (c) <= 'z')
> > #define isalpha(c)  (isupper(c)||islower(c))
> > 
> > if (!isalpha(name[0]))
> > return (0);
> > 
> > You can also expand the defines if you want.
> > I feel the intention here is to check if this is a interface group. So
> > maybe using the check in pfi_skip_if() would be better:
> > 
> > if (name[n-1] >= '0' && name[n-1] <= '9')
> > return (0); /* group names may not end in a digit */
> > 
> 
> it is just sanity check we deal with either interface or group,
> so isalpha(name[0]) is exactly what I want. And thanks for tip
> to steal it from libsa/stand.h. Perhaps one day some day there
> will be ctype.h for for kernel as well.
> 
> the reason to add this extra check is that I want to be sure we eventually
> don't create interface, which starts with space (white char).
> 
> Remember former code did not create interface (kif object), it just walked
> through list of existing interfaces in table. Now the DIOCSETIFFLAG ioctl
> needs to be more cautious.
> 
> 
> updated diff is below.

One more thing to consider, I think the following test in pfi_set_flags():

> + if ((p->pfik_flags_new != p->pfik_flags) &&
> + (p->pfik_flagrefs == 0))
> + pfi_kif_ref(p, PFI_KIF_REF_FLAG);

should actually check for the PFI_IFLAG_SKIP flag and not any flag.

if (ISSET(p->pfik_flags_new, PFI_IFLAG_SKIP) &&
p->pfik_flagrefs == 0)
pfi_kif_ref(p, PFI_KIF_REF_FLAG);

Same goes for pfi_clear_flags() just in reverse:

> + if ((p->pfik_flags_new != p->pfik_flags) &&
> + (p->pfik_flagrefs == 1))
> + pfi_kif_unref(p, PFI_KIF_REF_FLAG);

Should be changed to:
if (!ISSET(p->pfik_flags_new, PFI_IFLAG_SKIP) &&
p->pfik_flagrefs == 1)
pfi_kif_unref(p, PFI_KIF_REF_FLAG);

We only want to track the PFI_IFLAG_SKIP flag but not any other flag like
PFI_IFLAG_ANY. At least I think we want to do that, but then I guess
pfi_set_flags() should only add a kif
if (found == 0 && ISSET(flags, PFI_IFLAG_SKIP))

I don't really like pfi_set_flags() and pfi_clear_flags()
and their ioctls DIOCSETIFFLAG and DIOCCLRIFFLAG. There are no checks for
valid flag combinations. So anything goes for these functions.
Also should the name check not happen in the ioctl handler and return
EINVAL for bad input?

 
> 8<---8<---8<--8<
> index 8de37375ab4..383b8c38f6a 100644
> --- a/sys/net/pf_if.c
> +++ b/sys/net/pf_if.c
> +void
> +pfi_group_delmember(const char *group, struct ifnet *ifp)
> +{
> + struct pfi_kif  *gkif, *ikif;
> +
> + if ((gkif = pfi_kif_get(group, NULL)) == NULL ||
> + (ikif = pfi_kif_get(ifp->if_xname, NULL)) == NULL)
> + panic("%s: pfi_kif_get failed", __func__);
> + ikif->pfik_flags_new = ikif->pfik_flags & ~gkif->pfik_flags;
> +
> + pfi_group_change(group);
> +}
> +
>  void
>  pfi_group_addmember(const char *group, struct ifnet *ifp)
>  {
> @@ -361,7 +395,7 @@ pfi_group_addmember(const char *group, struct ifnet *ifp)
>   if ((gkif = pfi_kif_get(group, NULL)) == NULL ||
>   (ikif = pfi_kif_get(ifp->if_xname, NULL)) == NULL)
>   panic("%s: pfi_kif_get failed", __func__);
> - ikif->pfik_flags |= gkif->pfik_flags;
> + ikif->pfik_flags_new = ikif->pfik_flags | gkif->pfik_flags;
>  
>   pfi_group_change(group);
>  }
> @@ -786,25 +820,64 @@ int
>  pfi_set_flags(const char *name, int flags)
>  {
>   struct pfi_kif  *p;
> + int found = 0;
> + size_t n;
>  

rpki-client rrdp regress test

2021-11-25 Thread Claudio Jeker
This add an RRDP regress test that checks basic operation.
It checks some valid notification, snapshot and delta XML.
There are also two XML attacks included (billion laughs and XXE).
More bad XML files should be added.

Comments?
-- 
:wq Claudio

Index: Makefile.inc
===
RCS file: /cvs/src/regress/usr.sbin/rpki-client/Makefile.inc,v
retrieving revision 1.15
diff -u -p -r1.15 Makefile.inc
--- Makefile.inc24 Oct 2021 17:54:28 -  1.15
+++ Makefile.inc24 Nov 2021 14:12:39 -
@@ -8,6 +8,7 @@ PROGS += test-gbr
 PROGS += test-mft
 PROGS += test-roa
 PROGS += test-tal
+PROGS += test-rrdp
 
 .for p in ${PROGS}
 REGRESS_TARGETS += run-regress-$p
@@ -50,3 +51,35 @@ SRCS_test-tal+=  test-tal.c tal.c ip.c io
encoding.c print.c dummy.c
 run-regress-test-tal: test-tal
./test-tal -v ${.CURDIR}/../tal/*.tal
+
+SRCS_test-rrdp+=   test-rrdp.c rrdp_delta.c rrdp_notification.c \
+   rrdp_snapshot.c rrdp_util.c \
+   log.c encoding.c ip.c validate.c dummy.c
+LDADD_test-rrdp+=  -lexpat ${LDADD}
+DPADD_test-rrdp+=  ${LIBEXPAT} ${DPADD}
+run-regress-test-rrdp: test-rrdp
+   ./test-rrdp \
+   -n < ${.CURDIR}/../rrdp/notification.xml 2>&1 | tee rrdp-r1.out
+   cmp ${.CURDIR}/../rrdp/rrdp-r1.out rrdp-r1.out
+
+   ./test-rrdp -S 8fe05c2e-047d-49e7-8398-cd4250a572b1 -N 50500 \
+   -n < ${.CURDIR}/../rrdp/notification.xml 2>&1 | tee rrdp-r2.out
+   cmp ${.CURDIR}/../rrdp/rrdp-r2.out rrdp-r2.out
+   
+   ./test-rrdp -S 9b3f7e31-4979-ef8c-d818-73e4dadc3e6b -N 13755 \
+   -H 27571e365a4c87b51a03731415ce2118cc268d686db3209ae752f01ba2d74bc5 \
+   -d < ${.CURDIR}/../rrdp/delta.xml 2>&1 | tee rrdp-r3.out
+   cmp ${.CURDIR}/../rrdp/rrdp-r3.out rrdp-r3.out
+
+   ./test-rrdp -S 7e7d2563-5bbb-40b0-8723-6a2e90c85d9e -N 28483 \
+   -H 2a051bfd199150fe6bcdc777d09e70fe1acdf239fbf98ba378a793685e5adb21 \
+   -s < ${.CURDIR}/../rrdp/snapshot.xml 2>&1 | tee rrdp-r4.out
+   cmp ${.CURDIR}/../rrdp/rrdp-r4.out rrdp-r4.out
+
+   ./test-rrdp \
+   -n < ${.CURDIR}/../rrdp/xxe.xml 2>&1 | tee rrdp-r5.out
+   cmp ${.CURDIR}/../rrdp/rrdp-r5.out rrdp-r5.out
+
+   ./test-rrdp \
+   -n < ${.CURDIR}/../rrdp/billion_lol.xml 2>&1 | tee rrdp-r6.out
+   cmp ${.CURDIR}/../rrdp/rrdp-r6.out rrdp-r6.out
Index: test-rrdp.c
===
RCS file: test-rrdp.c
diff -N test-rrdp.c
--- /dev/null   1 Jan 1970 00:00:00 -
+++ test-rrdp.c 24 Nov 2021 17:34:37 -
@@ -0,0 +1,338 @@
+/* $OpenBSD: rrdp.c,v 1.17 2021/10/29 09:27:36 claudio Exp $ */
+/*
+ * Copyright (c) 2020 Nils Fisher 
+ * Copyright (c) 2021 Claudio Jeker 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include "extern.h"
+#include "rrdp.h"
+
+#define REGRESS_NOTIFY_URI "https://rpki.example.com/notify.xml;
+
+#define MAX_SESSIONS   12
+#defineREAD_BUF_SIZE   (32 * 1024)
+
+#define RRDP_STATE_REQ 0x01
+#define RRDP_STATE_WAIT0x02
+#define RRDP_STATE_PARSE   0x04
+#define RRDP_STATE_PARSE_ERROR 0x08
+#define RRDP_STATE_PARSE_DONE  0x10
+#define RRDP_STATE_HTTP_DONE   0x20
+#define RRDP_STATE_DONE(RRDP_STATE_PARSE_DONE | 
RRDP_STATE_HTTP_DONE)
+
+struct rrdp {
+   TAILQ_ENTRY(rrdp)entry;
+   size_t   id;
+   char*notifyuri;
+   char*local;
+   char*last_mod;
+
+   struct pollfd   *pfd;
+   int  infd;
+   int  state;
+   unsigned int file_pending;
+   unsigned int file_failed;
+   enum http_result res;
+   enum rrdp_task   task;
+
+   char hash[SHA256_DIGEST_LENGTH];
+   SHA256_CTX   ctx;
+
+   struct rrdp_session  repository;
+   struct rrdp_sessi

Re: make 'set skip on ...' dynamic

2021-11-25 Thread Claudio Jeker
On Fri, Nov 19, 2021 at 12:59:38AM +0100, Alexandr Nedvedicky wrote:
> Hello,
> 
> it has turned out things are bit more complicated when it comes to interface
> groups. diff below makes following scenario work for me.
> 
> we start with etc/pf.conf as follows:
> 
>   # cat /etc/pf.conf
>   set skip on lo
>   set skip on test1
>   set skip on test2
>   set skip on agroup
>   block return
> 
> Let's see what interfaces are known to pf(4)
> 
>   # pfctl -sI
>   agroup
>   all
>   carp
>   egress
>   enc
>   enc0
>   lo
>   lo0
>   pflog
>   pflog0
>   test1
>   test2
>   vio0
> 
> Using the same rules on current we get different output:
> 
>   # pfctl -sI
>   all
>   carp
>   egress
>   enc
>   enc0
>   lo
>   lo0
>   pflog
>   pflog0
>   vio0
> 
> as you can see test1, test2 and agroup are missing on current.
> it's because the current does not create a pfi_kif entry for
> interfaces/groups referred by 'set skip on' keyword in pf.conf.
> 
> the rules found in /etc/pf.conf block all network traffic:
> 
>   # ping -c 1 192.168.2.1 
>   PING 192.168.2.1 (192.168.2.1): 56 data bytes
>   ping: sendmsg: Permission denied
>   ping: wrote 192.168.2.1 64 chars, ret=-1
> 
>   --- 192.168.2.1 ping statistics ---
>   1 packets transmitted, 0 packets received, 100.0% packet loss
> 
> to demonstrate 'set skip on agroup' works I'll add vio0 interface into
> agroup and repeat test:
> 
>   # ifconfig vio0 group agroup
>   # ping -c 1 192.168.2.1 
>   PING 192.168.2.1 (192.168.2.1): 56 data bytes
>   64 bytes from 192.168.2.1: icmp_seq=0 ttl=254 time=1.058 ms
> 
>   --- 192.168.2.1 ping statistics ---
>   1 packets transmitted, 1 packets received, 0.0% packet loss
>   round-trip min/avg/max/std-dev = 1.058/1.058/1.058/0.000 ms
> 
> removing vio0 from agroup stops network again:
> 
>   # ifconfig vio0 -group agroup   
>   # ping -c 1 192.168.2.1   
>   PING 192.168.2.1 (192.168.2.1): 56 data bytes
>   ping: sendmsg: Permission denied
>   ping: wrote 192.168.2.1 64 chars, ret=-1
> 
>   --- 192.168.2.1 ping statistics ---
>   1 packets transmitted, 0 packets received, 100.0% packet loss
> 
> removing 'set skip on agroup' from /etc/pf.conf also removes
> the matching pfi_kif object from interface table kept by pf(4):
> 
>   # cat /etc/pf.conf
>   set skip on lo
>   set skip on test1
>   set skip on test2
>   block return
>   # pfctl -f /etc/pf.conf
>   # pfctl -sI
>   all
>   carp
>   egress
>   enc
>   enc0
>   lo
>   lo0
>   pflog
>   pflog0
>   test1
>   test2
>   vio0
> 
> 
> The main trick to get things to work is to let 'set skip on ...' create 
> entries
> (pfi_kif objects)) in pf's table for interfaces and groups which are not known
> to IP stack yet. The same thing happens when firewall rule refers interface,
> which does not exist in system yet. Diff below modifies pfi_set_flags()
> function to create pfi_kif object if it does not already. We also obtain
> a reference PFI_KIF_REF_FLAG if and only if the flag is being changed.
> 
> We treat a pfik_reflag reference counter as an indication whether the pfi_kif
> object get created on behalf of 'set skip on ...' keyword, so we can call
> pfi_kif_unref() in pfi_clear_flags() to destroy it. The pfik_reflag also
> prevents other callers to pfi_kif_unref() from destroying pfi_kif, which
> got created by pfi_set_flags().
> 
> Changes described so far are sufficient to get 'set skip on...' working for
> regular interfaces. To make it working for interface group we need to 
> introduce
> pfi_group_delmember() and slightly adjust pfi_group_addmember().
> Both functions update interface flag in the same fashion like pfi_set_flags()
> and pfi_clear_flags(). The caller of 
> pfi_group_delmember()/pfi_group_addmember()
> must call pfi_xcommit() to update interfaces.
> 
> OK?

Some inline comments.


> 8<---8<---8<--8<
> diff --git a/share/man/man5/pf.conf.5 b/share/man/man5/pf.conf.5
> index bff448aa8dc..4afe841651f 100644
> --- a/share/man/man5/pf.conf.5
> +++ b/share/man/man5/pf.conf.5
> @@ -1383,9 +1383,6 @@ Packets passing in or out on such interfaces are passed 
> as if pf was
>  disabled, i.e. pf does not process them in any way.
>  This can be useful on loopback and other virtual interfaces, when
>  packet filtering is not desired and can have unexpected effects.
> -.Ar ifspec
> -is only evaluated when the ruleset is loaded; interfaces created
> -later will not be skipped.
>  PF filters traffic on all interfaces by default.
>  .It Ic set Cm state-defaults Ar state-option , ...
>  The
> diff --git a/sys/net/if.c b/sys/net/if.c
> index 

Re: rpki-client: set repo_timeout to be 1/4th of timeout

2021-11-25 Thread Claudio Jeker
On Thu, Nov 25, 2021 at 12:54:49PM +, Job Snijders wrote:
> Replace MAX_REPO_TIMEOUT with repo_timeout, which is set to 1/4th of
> timeout, or if timeout is disabled set it to 24 hours.
> 
> OK?

OK claudio@
 
> Index: extern.h
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
> retrieving revision 1.97
> diff -u -p -r1.97 extern.h
> --- extern.h  24 Nov 2021 15:24:16 -  1.97
> +++ extern.h  25 Nov 2021 12:52:05 -
> @@ -627,7 +627,4 @@ int   mkpath(const char *);
>  /* Maximum allowd repositories per tal */
>  #define MAX_REPO_PER_TAL 1000
>  
> -/* Timeout for repository synchronisation, in seconds */
> -#define MAX_REPO_TIMEOUT (15 * 60)
> -
>  #endif /* ! EXTERN_H */
> Index: main.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
> retrieving revision 1.165
> diff -u -p -r1.165 main.c
> --- main.c19 Nov 2021 09:47:30 -  1.165
> +++ main.c25 Nov 2021 12:52:05 -
> @@ -68,6 +68,7 @@ const char  *bird_tablename = "ROAS";
>  int  verbose;
>  int  noop;
>  int  rrdpon = 1;
> +int  repo_timeout = 15*60;
>  
>  struct stats  stats;
>  
> @@ -753,6 +754,12 @@ main(int argc, char *argv[])
>   timeout = strtonum(optarg, 0, 24*60*60, );
>   if (errs)
>   errx(1, "-s: %s", errs);
> + if (timeout == 0)
> + repo_timeout = 24*60*60;
> + else if (timeout < 300)
> + errx(1, "-s: %i too small", timeout);
> + else
> + repo_timeout = timeout / 4;
>   break;
>   case 't':
>   if (talsz >= TALSZ_MAX)
> Index: repo.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v
> retrieving revision 1.12
> diff -u -p -r1.12 repo.c
> --- repo.c15 Nov 2021 16:32:15 -  1.12
> +++ repo.c25 Nov 2021 12:52:05 -
> @@ -40,6 +40,7 @@
>  extern struct stats  stats;
>  extern int   noop;
>  extern int   rrdpon;
> +extern int   repo_timeout;
>  
>  enum repo_state {
>   REPO_LOADING = 0,
> @@ -620,7 +621,7 @@ repo_alloc(int talid)
>  
>   rp->id = ++repoid;
>   rp->talid = talid;
> - rp->alarm = getmonotime() + MAX_REPO_TIMEOUT;
> + rp->alarm = getmonotime() + repo_timeout;
>   TAILQ_INIT(>queue);
>   SLIST_INSERT_HEAD(, rp, entry);
>  
> @@ -1225,7 +1228,7 @@ static void
>  repo_fail(struct repo *rp)
>  {
>   /* reset the alarm since code may fallback to rsync */
> - rp->alarm = getmonotime() + MAX_REPO_TIMEOUT;
> + rp->alarm = getmonotime() + repo_timeout;
>  
>   if (rp->ta)
>   http_finish(rp->ta->id, HTTP_FAILED, NULL);
> Index: rpki-client.8
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/rpki-client.8,v
> retrieving revision 1.49
> diff -u -p -r1.49 rpki-client.8
> --- rpki-client.8 26 Oct 2021 13:26:53 -  1.49
> +++ rpki-client.8 25 Nov 2021 12:52:05 -
> @@ -131,6 +131,8 @@ seconds of runtime, because normal pract
>  .Xr cron 8 .
>  Disable by specifying 0.
>  Defaults to 1 hour.
> +Individual Publication Points are timed out after one fourth of
> +.Em timeout .
>  .It Fl T Ar table
>  For BIRD output generated with the
>  .Fl B
> 

-- 
:wq Claudio



Re: acme-client: another trivial accessor conversion

2021-11-22 Thread Claudio Jeker
On Mon, Nov 22, 2021 at 12:18:37AM +0100, Theo Buehler wrote:
> bio->num_write aka BIO_number_written(bio). Straightforward. The main
> reason I'm asking is that keeping the two else results in overlong lines
> and awkward line wrapping. So I decided to drop them hoping that's
> acceptable. Otherwise please tell me the preferred way to wrap the
> lines in this part of the tree.
> 
> Index: revokeproc.c
> ===
> RCS file: /cvs/src/usr.sbin/acme-client/revokeproc.c,v
> retrieving revision 1.18
> diff -u -p -r1.18 revokeproc.c
> --- revokeproc.c  13 Oct 2021 18:09:42 -  1.18
> +++ revokeproc.c  21 Nov 2021 23:07:37 -
> @@ -186,15 +186,17 @@ revokeproc(int fd, const char *certfile,
>   if (bio == NULL) {
>   warnx("BIO_new");
>   goto out;
> - } else if (!X509V3_EXT_print(bio, ex, 0, 0)) {
> + }
> + if (!X509V3_EXT_print(bio, ex, 0, 0)) {
>   warnx("X509V3_EXT_print");
>   goto out;
> - } else if ((san = calloc(1, bio->num_write + 1)) == NULL) {
> + }
> + if ((san = calloc(1, BIO_number_written(bio) + 1)) == NULL) {
>   warn("calloc");
>   goto out;
>   }
> - ssz = BIO_read(bio, san, bio->num_write);
> - if (ssz < 0 || (unsigned)ssz != bio->num_write) {
> + ssz = BIO_read(bio, san, BIO_number_written(bio));
> + if (ssz < 0 || (unsigned)ssz != BIO_number_written(bio)) {
>   warnx("BIO_read");
>   goto out;
>   }
> 

OK. These else if chaining is not OpenBSD style and makes the code hard to
read. I like to see less of them.

-- 
:wq Claudio



Re: vport: set UP on ip assign

2021-11-15 Thread Claudio Jeker
On Mon, Nov 15, 2021 at 12:23:02PM +, Klemens Nanni wrote:
> On Mon, Nov 15, 2021 at 12:00:18PM +1000, David Gwynne wrote:
> > On Sat, Nov 13, 2021 at 11:59:59PM +, Klemens Nanni wrote:
> > > Practically all interfaces pull itself up when IPs get assigned, but
> > > vport(4) does not.
> > 
> > Yes, I do (or don't do) this very deliberately when I get the chance.
> > 
> > > This broke IPv4 networking for me on a router I switched from bridge(4)
> > > to veb(4) because hostname.vport0 only contained the equivalent of
> > > 
> > >   descr LAN
> > >   inet 192.0.2.1
> > >   inet6 2001:db8::1
> > > 
> > > e.g. the explicit "up" was missing.
> > > 
> > > dhcpd(8) only considers UP interfaces to listen on during start;
> > > being the only interface it could potentially listen on, dhcpd thus
> > > ignored vport0 and failed to start.
> > > 
> > > `ifconfig vport0 up && rcctl restart dhcpd' fixed this.
> > > Adding "up" to thostname.vport0 also fixed it.
> > > 
> > > Nonetheless, vport should UP itself as the rest does.
> > 
> > My counter argument is that no interface should implicitly bring itself
> > up when an address is configured because it has been a road block to
> > figuring out how to lock the ioctl paths better, and it confuses error
> > handling. If address config works, but the interface fails to come up,
> > the address remains configured but we report an error. But it looks like
> > configuring an address failed? Wat.
> 
> That's a valid point, although I must say I never ran into this issue.
> 
> I fear that users have come to rely on the implicit up semantics, i.e.
> I doubt I'm the only one with hostname.* files lacking "up".

Sure people got used to this mode. I agree with dlg@ that the way that
this auto interface up happens is rather horrible from a network stack
view. Also it makes it impossible to configure an interface all the way
before bringing it up. This may be important for interfaces with more
complex configuration.

The current behaviour is great for casual users (that does not really
care about network) but is annoying for network admins.
 
> > I've suggested previously that netstart should handle bringing an
> > interface up. look for "netstart: implicit up and explicit down for
> > hostname.if conf files" on tech@. I didn't hanve the energy to push
> > it forward though.
> 
> I'll do the digging and try to catch up, thanks.

Another option is to adjust ifconfig but then again one would like to do
the up last after running multiple ifconfig calls. ifconfig has its own
madness when it comes to execute multiple commands in one go.
 
> > dhcpd should cope with an interface being down too. It should be about
> > whetherthe addresses are right more than if the interface is up or not.

I expect an interface that is down to remain down until I bring it up
again. Same goes the other way. ifconfig up/down should only be used to
implement admin shutdown. We fixed a few interfaces in the past that
played with IFF_UP in the driver.

-- 
:wq Claudio



Re: IPsec tdb ddb print

2021-11-18 Thread Claudio Jeker
On Thu, Nov 18, 2021 at 08:50:37AM +, Stuart Henderson wrote:
> On 2021/11/18 09:15, Claudio Jeker wrote:
> > On Thu, Nov 18, 2021 at 08:10:26AM +, Stuart Henderson wrote:
> > > On 2021/11/15 17:23, Alexander Bluhm wrote:
> > > > +   DUMP(ids, "%p");
> > > > +   DUMP(ids_swapped, "%d");
> > > > +   DUMP(mtu, "%d");
> > > > +   DUMP(mtutimeout, "%lld");
> > > > +   pr("%18s: %08x\n", "udpencap_port",
> > > > +   ntohl(tdb->tdb_udpencap_port));
> > > 
> > > ntohl is incorrect here:
> > > 
> > >  udpencap_port: 1194
> > > 
> > > Index: netinet/ip_ipsp.c
> > > ===
> > > RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v
> > > retrieving revision 1.250
> > > diff -u -p -r1.250 ip_ipsp.c
> > > --- netinet/ip_ipsp.c 16 Nov 2021 13:53:14 -  1.250
> > > +++ netinet/ip_ipsp.c 18 Nov 2021 08:08:47 -
> > > @@ -591,8 +591,7 @@ tdb_printit(void *addr, int full, int (*
> > >   DUMP(ids_swapped, "%d");
> > >   DUMP(mtu, "%d");
> > >   DUMP(mtutimeout, "%lld");
> > > - pr("%18s: %08x\n", "udpencap_port",
> > > - ntohl(tdb->tdb_udpencap_port));
> > > + pr("%18s: %08x\n", "udpencap_port", tdb->tdb_udpencap_port);
> > >   DUMP(tag, "%d");
> > >   DUMP(tap, "%d");
> > >   DUMP(rdomain, "%d");
> > > 
> > 
> > I think this needs to be ntohs(tdb->tdb_udpencap_port) since it is still
> > stored in network byte order.
> 
> With ntohs, it's "udpencap_port: "

I would also use %d as format string. This is just a simple portnumber.

The code using tdb_udpencap_port for sure assumes network byte order:
uh->uh_sport = uh->uh_dport = htons(udpencap_port);
if (tdb->tdb_udpencap_port)
uh->uh_dport = tdb->tdb_udpencap_port;

-- 
:wq Claudio



Re: IPsec tdb ddb print

2021-11-18 Thread Claudio Jeker
On Thu, Nov 18, 2021 at 08:10:26AM +, Stuart Henderson wrote:
> On 2021/11/15 17:23, Alexander Bluhm wrote:
> > +   DUMP(ids, "%p");
> > +   DUMP(ids_swapped, "%d");
> > +   DUMP(mtu, "%d");
> > +   DUMP(mtutimeout, "%lld");
> > +   pr("%18s: %08x\n", "udpencap_port",
> > +   ntohl(tdb->tdb_udpencap_port));
> 
> ntohl is incorrect here:
> 
>  udpencap_port: 1194
> 
> Index: netinet/ip_ipsp.c
> ===
> RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v
> retrieving revision 1.250
> diff -u -p -r1.250 ip_ipsp.c
> --- netinet/ip_ipsp.c 16 Nov 2021 13:53:14 -  1.250
> +++ netinet/ip_ipsp.c 18 Nov 2021 08:08:47 -
> @@ -591,8 +591,7 @@ tdb_printit(void *addr, int full, int (*
>   DUMP(ids_swapped, "%d");
>   DUMP(mtu, "%d");
>   DUMP(mtutimeout, "%lld");
> - pr("%18s: %08x\n", "udpencap_port",
> - ntohl(tdb->tdb_udpencap_port));
> + pr("%18s: %08x\n", "udpencap_port", tdb->tdb_udpencap_port);
>   DUMP(tag, "%d");
>   DUMP(tap, "%d");
>   DUMP(rdomain, "%d");
> 

I think this needs to be ntohs(tdb->tdb_udpencap_port) since it is still
stored in network byte order.

-- 
:wq Claudio



Re: rpki-client: make maximum number of publication points to sync operator configurable

2021-11-25 Thread Claudio Jeker
On Thu, Nov 25, 2021 at 08:18:10PM +0100, Sebastian Benoit wrote:
> Job Snijders(j...@openbsd.org) on 2021.11.25 16:13:51 +:
> > It might be advantageous to permit operators to optionally specify the
> > maximum number of publication points with which rpki-client will
> > synchronize.
> > 
> > For example: "doas rpki-client -m 1 -t /etc/rpki/ripe.tal" has as effect
> > that only RIPE NCC's repository is contacted, but none of the delegated
> > repositories.
> > 
> > This flag perhaps permits us to start shipping with a more conservative
> > default than 1000, like 100 or 200. It is clear that encouraging the
> > ecosystem to embrace 'Publish in Parent' is a saner model than everyone
> > running their own delegation.
> > 
> > Thoughts?
> 
> Yes, if we dont have these configurable, we will have users running into
> them eventually and be sad.

I'm not a big fan of this config option. This is for sure not something
that needs to change between runs and abusing it for the -m 1 case seems
strange.
Will we end up with a option salad for each and every limit? I think this
is a bad direction. rpki-client should just work and the limits need to be
chosen with that in mind.
 
> maxpubpoints sounds a bit funny, but i have no other idea.
> 
> code reads ok.

The way the limit is implemented in this patch is not correct.
 
More inline

> > Index: main.c
> > ===
> > RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
> > retrieving revision 1.166
> > diff -u -p -r1.166 main.c
> > --- main.c  25 Nov 2021 14:03:40 -  1.166
> > +++ main.c  25 Nov 2021 16:08:10 -
> > @@ -69,6 +69,7 @@ int   verbose;
> >  intnoop;
> >  intrrdpon = 1;
> >  intrepo_timeout = 15*60;
> > +unsigned int   maxpubpoints = 1000;
> >  
> >  struct statsstats;
> >  
> > @@ -714,7 +715,7 @@ main(int argc, char *argv[])
> > "proc exec unveil", NULL) == -1)
> > err(1, "pledge");
> >  
> > -   while ((c = getopt(argc, argv, "b:Bcd:e:f:jnorRs:t:T:vV")) != -1)
> > +   while ((c = getopt(argc, argv, "b:Bcd:e:f:jm:norRs:t:T:vV")) != -1)
> > switch (c) {
> > case 'b':
> > bind_addr = optarg;
> > @@ -738,6 +739,11 @@ main(int argc, char *argv[])
> > case 'j':
> > outformats |= FORMAT_JSON;
> > break;
> > +   case 'm':
> > +   maxpubpoints = strtonum(optarg, 0, 10, );
> > +   if (errs)
> > +   errx(1, "-m: %s", errs);
> > +   break;

Why allow 0 as minimum? Will that even work?

> > case 'n':
> > noop = 1;
> > break;
> > @@ -1220,7 +1226,7 @@ usage:
> > fprintf(stderr,
> > "usage: rpki-client [-BcjnoRrVv] [-b sourceaddr] [-d cachedir]"
> > " [-e rsync_prog]\n"
> > -   "   [-s timeout] [-T table] [-t tal]"
> > -   " [outputdir]\n");
> > +   "   [-m maxpubpoints] [-s timeout] [-T table] "
> > +   "[-t tal] [outputdir]\n");
> > return 1;
> >  }
> > Index: repo.c
> > ===
> > RCS file: /cvs/src/usr.sbin/rpki-client/repo.c,v
> > retrieving revision 1.14
> > diff -u -p -r1.14 repo.c
> > --- repo.c  25 Nov 2021 14:03:40 -  1.14
> > +++ repo.c  25 Nov 2021 16:08:17 -
> > @@ -41,6 +41,7 @@ extern struct stats   stats;
> >  extern int noop;
> >  extern int rrdpon;
> >  extern int repo_timeout;
> > +extern unsigned intmaxpubpoints;
> >  
> >  enum repo_state {
> > REPO_LOADING = 0,
> > @@ -1100,12 +1101,14 @@ ta_lookup(int id, struct tal *tal)
> > if ((rp->repouri = strdup(tal->descr)) == NULL)
> > err(1, NULL);
> >  
> > -   if (++talrepocnt[id] >= MAX_REPO_PER_TAL) {
> > -   if (talrepocnt[id] == MAX_REPO_PER_TAL)
> > -   warnx("too many repositories under %s", tals[id]);
> > +   if (talrepocnt[id] >= maxpubpoints + 1) {
> > +   if (talrepocnt[id] == maxpubpoints)

This can not be right. If the first if is true the 2nd can never be true.

> > +   warnx("too many publication points under %s", tals[id]);
> > nofetch = 1;
> > }
> >  
> > +   talrepocnt[id]++;
> > +
> > rp->ta = ta_get(tal, nofetch);
> >  
> > return rp;
> > @@ -1146,11 +1149,12 @@ repo_lookup(int id, const char *uri, con
> > if ((rp->notifyuri = strdup(notify)) == NULL)
> > err(1, NULL);
> >  
> > -   if (++talrepocnt[id] >= MAX_REPO_PER_TAL) {
> > -   if (talrepocnt[id] == MAX_REPO_PER_TAL)
> > -   warnx("too many repositories under %s", tals[id]);
> > +   if (talrepocnt[id] >= maxpubpoints + 1) {
> > +   if (talrepocnt[id] == maxpubpoints)

Same here.

> > +   warnx("too many publication points 

rpki-client adjust tal parse to the BIO free world

2021-10-26 Thread Claudio Jeker
This is part 3 of the BIO removal. Switch tal_parse to pass a file buffer
like all other callers. The parent process can now just use load_file()
and pass that buffer to the parser. From there on the magic just happens.

-- 
:wq Claudio

Index: encoding.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/encoding.c,v
retrieving revision 1.4
diff -u -p -r1.4 encoding.c
--- encoding.c  11 Oct 2021 16:06:36 -  1.4
+++ encoding.c  26 Oct 2021 14:40:47 -
@@ -29,11 +29,11 @@
  * Returns 0 on success or -1 for any errors.
  */
 int
-base64_decode(const unsigned char *in, unsigned char **out, size_t *outlen)
+base64_decode(const unsigned char *in, size_t inlen,
+unsigned char **out, size_t *outlen)
 {
static EVP_ENCODE_CTX *ctx;
unsigned char *to;
-   size_t inlen;
int tolen;
 
if (ctx == NULL && (ctx = EVP_ENCODE_CTX_new()) == NULL)
@@ -42,7 +42,6 @@ base64_decode(const unsigned char *in, u
*out = NULL;
*outlen = 0;
 
-   inlen = strlen(in);
if (inlen >= INT_MAX - 3)
return -1;
tolen = ((inlen + 3) / 4) * 3 + 1;
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.79
diff -u -p -r1.79 extern.h
--- extern.h26 Oct 2021 13:31:05 -  1.79
+++ extern.h26 Oct 2021 14:40:37 -
@@ -337,12 +337,12 @@ enum publish_type {
  * and parsed.
  */
 struct entity {
-   enum rtype   type; /* type of entity (not RTYPE_EOF) */
-   char*file; /* local path to file */
-   int  has_pkey; /* whether pkey/sz is specified */
-   unsigned char   *pkey; /* public key (optional) */
-   size_t   pkeysz; /* public key length (optional) */
-   char*descr; /* tal description */
+   enum rtype   type;  /* type of entity (not RTYPE_EOF) */
+   char*file;  /* local path to file */
+   int  has_data;  /* whether data blob is specified */
+   unsigned char   *data;  /* optional data blob */
+   size_t   datasz;/* length of optional data blob */
+   char*descr; /* tal description */
TAILQ_ENTRY(entity) entries;
 };
 TAILQ_HEAD(entityq, entity);
@@ -397,8 +397,7 @@ extern int verbose;
 
 voidtal_buffer(struct ibuf *, const struct tal *);
 voidtal_free(struct tal *);
-struct tal *tal_parse(const char *, char *);
-char   *tal_read_file(const char *);
+struct tal *tal_parse(const char *, char *, size_t);
 struct tal *tal_read(struct ibuf *);
 
 voidcert_buffer(struct ibuf *, const struct cert *);
@@ -534,8 +533,8 @@ void cryptoerrx(const char *, ...)
 
 /* Encoding functions for hex and base64. */
 
-int base64_decode(const unsigned char *, unsigned char **,
-   size_t *);
+int base64_decode(const unsigned char *, size_t,
+   unsigned char **, size_t *);
 int base64_encode(const unsigned char *, size_t, char **);
 char   *hex_encode(const unsigned char *, size_t);
 
@@ -595,8 +594,9 @@ int  output_csv(FILE *, struct vrp_tree
 int output_json(FILE *, struct vrp_tree *, struct brk_tree *,
struct stats *);
 
-void   logx(const char *fmt, ...)
+void   logx(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
+unsigned char  *load_file(const char *, size_t *);
 
 intmkpath(const char *);
 
Index: main.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.154
diff -u -p -r1.154 main.c
--- main.c  24 Oct 2021 21:24:19 -  1.154
+++ main.c  26 Oct 2021 14:38:40 -
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -82,13 +83,46 @@ logx(const char *fmt, ...)
}
 }
 
+unsigned char *
+load_file(const char *name, size_t *len)
+{
+   unsigned char *buf = NULL;
+   struct stat st;
+   ssize_t n;
+   size_t size;
+   int fd;
+
+   *len = 0;
+
+   if ((fd = open(name, O_RDONLY)) == -1)
+   return NULL;
+   if (fstat(fd, ) != 0)
+   goto err;
+   if (st.st_size < 0)
+   goto err;
+   size = (size_t)st.st_size;
+   if ((buf = malloc(size)) == NULL)
+   goto err;
+   n = read(fd, buf, size);
+   if (n < 0 || (size_t)n != size)
+   goto err;
+   close(fd);
+   *len = size;
+   return buf;
+
+err:
+   close(fd);
+   free(buf);
+   return NULL;
+}
+
 void
 entity_free(struct entity *ent)
 {
if (ent == NULL)
return;
 
-   free(ent->pkey);
+   free(ent->data);
  

remove more BIO from rpki-client

2021-10-26 Thread Claudio Jeker
I want to be able to pass a buffer to the various parser functions instead
of a filename. This is in preparation for supporting rpki-client -f somefile

This diff switches CMS and CRL to their regular d2i versions. The cert
files will follow in the next diff.
-- 
:wq Claudio

Index: cms.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/cms.c,v
retrieving revision 1.10
diff -u -p -r1.10 cms.c
--- cms.c   9 Sep 2021 14:15:49 -   1.10
+++ cms.c   26 Oct 2021 09:43:10 -
@@ -35,14 +35,12 @@
  * Return the eContent as a string and set "rsz" to be its length.
  */
 unsigned char *
-cms_parse_validate(X509 **xp, const char *fn, const ASN1_OBJECT *oid,
-size_t *rsz)
+cms_parse_validate(X509 **xp, const char *fn, const unsigned char *der,
+size_t derlen, const ASN1_OBJECT *oid, size_t *rsz)
 {
const ASN1_OBJECT   *obj;
ASN1_OCTET_STRING   **os = NULL;
-   BIO *bio = NULL;
CMS_ContentInfo *cms;
-   FILE*f;
int  rc = 0;
STACK_OF(X509)  *certs = NULL;
unsigned char   *res = NULL;
@@ -50,21 +48,11 @@ cms_parse_validate(X509 **xp, const char
*rsz = 0;
*xp = NULL;
 
-   /*
-* This is usually fopen() failure, so let it pass through to
-* the handler, which will in turn ignore the entity.
-*/
-   if ((f = fopen(fn, "rb")) == NULL) {
-   warn("%s", fn);
-   return NULL;
-   }
-
-   if ((bio = BIO_new_fp(f, BIO_CLOSE)) == NULL) {
-   cryptowarnx("%s: BIO_new_fp", fn);
+   /* just fail for empty buffers, the warning was printed elsewhere */
+   if (der == NULL)
return NULL;
-   }
 
-   if ((cms = d2i_CMS_bio(bio, NULL)) == NULL) {
+   if ((cms = d2i_CMS_ContentInfo(NULL, , derlen)) == NULL) {
cryptowarnx("%s: RFC 6488: failed CMS parse", fn);
goto out;
}
@@ -74,8 +62,8 @@ cms_parse_validate(X509 **xp, const char
 * Verify that the self-signage is correct.
 */
 
-   if (!CMS_verify(cms, NULL, NULL,
-   NULL, NULL, CMS_NO_SIGNER_CERT_VERIFY)) {
+   if (!CMS_verify(cms, NULL, NULL, NULL, NULL,
+   CMS_NO_SIGNER_CERT_VERIFY)) {
cryptowarnx("%s: RFC 6488: CMS not self-signed", fn);
goto out;
}
@@ -134,7 +122,6 @@ cms_parse_validate(X509 **xp, const char
 
rc = 1;
 out:
-   BIO_free_all(bio);
sk_X509_free(certs);
CMS_ContentInfo_free(cms);
 
Index: crl.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/crl.c,v
retrieving revision 1.10
diff -u -p -r1.10 crl.c
--- crl.c   29 Jan 2021 10:13:16 -  1.10
+++ crl.c   26 Oct 2021 09:43:18 -
@@ -29,32 +29,22 @@
 #include "extern.h"
 
 X509_CRL *
-crl_parse(const char *fn)
+crl_parse(const char *fn, const unsigned char *der, size_t len)
 {
int  rc = 0;
X509_CRL*x = NULL;
-   BIO *bio = NULL;
-   FILE*f;
 
-   if ((f = fopen(fn, "rb")) == NULL) {
-   warn("%s", fn);
+   /* just fail for empty buffers, the warning was printed elsewhere */
+   if (der == NULL)
return NULL;
-   }
-
-   if ((bio = BIO_new_fp(f, BIO_CLOSE)) == NULL) {
-   if (verbose > 0)
-   cryptowarnx("%s: BIO_new_file", fn);
-   return NULL;
-   }
 
-   if ((x = d2i_X509_CRL_bio(bio, NULL)) == NULL) {
-   cryptowarnx("%s: d2i_X509_CRL_bio", fn);
+   if ((x = d2i_X509_CRL(NULL, , len)) == NULL) {
+   cryptowarnx("%s: d2i_X509_CRL", fn);
goto out;
}
 
rc = 1;
 out:
-   BIO_free_all(bio);
if (rc == 0) {
X509_CRL_free(x);
x = NULL;
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.77
diff -u -p -r1.77 extern.h
--- extern.h24 Oct 2021 17:53:07 -  1.77
+++ extern.h25 Oct 2021 18:42:49 -
@@ -410,22 +410,25 @@ void   cert_insert_brks(struct brk_tree 
 
 voidmft_buffer(struct ibuf *, const struct mft *);
 voidmft_free(struct mft *);
-struct mft *mft_parse(X509 **, const char *);
+struct mft *mft_parse(X509 **, const char *, const unsigned char *,
+   size_t);
 int mft_check(const char *, struct mft *);
 struct mft *mft_read(struct ibuf *);
 
 voidroa_buffer(struct ibuf *, const struct roa *);
 voidroa_free(struct roa *);
-struct roa *roa_parse(X509 **, const char *);
+struct roa *roa_parse(X509 **, const char *, const unsigned char *,
+   

openrsync add --max-size and --min-size support

2021-10-28 Thread Claudio Jeker
This diff should implement --max-size and --min-size almost equivalent to
GNU rsync. I decided to use scan_scaled() instead of building something
new that handles all the extra bits GNU rsync has.
The remote rsync process gets the sizes in bytes so scaling is just a
local issue.

Manpage probably needs more love.
-- 
:wq Claudio

Index: Makefile
===
RCS file: /cvs/src/usr.bin/rsync/Makefile,v
retrieving revision 1.12
diff -u -p -r1.12 Makefile
--- Makefile22 Oct 2021 11:10:34 -  1.12
+++ Makefile28 Oct 2021 14:06:07 -
@@ -4,8 +4,8 @@ PROG=   openrsync
 SRCS=  blocks.c client.c copy.c downloader.c fargs.c flist.c hash.c ids.c \
io.c log.c main.c misc.c mkpath.c mktemp.c receiver.c rmatch.c \
rules.c sender.c server.c session.c socket.c symlinks.c uploader.c
-LDADD+= -lcrypto -lm
-DPADD+= ${LIBCRYPTO} ${LIBM}
+LDADD+= -lcrypto -lm -lutil
+DPADD+= ${LIBCRYPTO} ${LIBM} ${LIBUTIL}
 MAN=   openrsync.1
 
 CFLAGS+= -Wall -Wextra
Index: extern.h
===
RCS file: /cvs/src/usr.bin/rsync/extern.h,v
retrieving revision 1.42
diff -u -p -r1.42 extern.h
--- extern.h22 Oct 2021 11:10:34 -  1.42
+++ extern.h28 Oct 2021 13:59:20 -
@@ -141,6 +141,8 @@ struct  opts {
int  numeric_ids;   /* --numeric-ids */
int  one_file_system;   /* -x */
int  alt_base_mode;
+   off_tmax_size;  /* --max-size */
+   off_tmin_size;  /* --min-size */
char*rsync_path;/* --rsync-path */
char*ssh_prog;  /* --rsh or -e */
char*port;  /* --port */
Index: fargs.c
===
RCS file: /cvs/src/usr.bin/rsync/fargs.c,v
retrieving revision 1.20
diff -u -p -r1.20 fargs.c
--- fargs.c 22 Oct 2021 11:10:34 -  1.20
+++ fargs.c 28 Oct 2021 14:09:23 -
@@ -131,6 +131,10 @@ fargs_cmdline(struct sess *sess, const s
if (!sess->opts->specials && sess->opts->devices)
/* --devices is sent as -D --no-specials */
addargs(, "--no-specials");
+   if (sess->opts->max_size >= 0)
+   addargs(, "--max-size=%lld", sess->opts->max_size);
+   if (sess->opts->min_size >= 0)
+   addargs(, "--min-size=%lld", sess->opts->min_size);
 
/* only add --compare-dest, etc if this is the sender */
if (sess->opts->alt_base_mode != 0 && 
Index: main.c
===
RCS file: /cvs/src/usr.bin/rsync/main.c,v
retrieving revision 1.61
diff -u -p -r1.61 main.c
--- main.c  28 Oct 2021 13:07:43 -  1.61
+++ main.c  28 Oct 2021 15:17:39 -
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "extern.h"
 
@@ -341,7 +342,7 @@ main(int argc, char *argv[])
pid_tchild;
int  fds[2], sd = -1, rc, c, st, i, lidx;
size_t   basedir_cnt = 0;
-   struct sess   sess;
+   struct sess  sess;
struct fargs*fargs;
char**args;
const char  *errstr;
@@ -352,6 +353,8 @@ main(int argc, char *argv[])
NULL) == -1)
err(ERR_IPC, "pledge");
 
+   opts.max_size = opts.min_size = -1;
+
while ((c = getopt_long(argc, argv, "Dae:ghlnoprtvxz", lopts, ))
!= -1) {
switch (c) {
@@ -472,8 +475,12 @@ basedir:
opts.basedir[basedir_cnt++] = optarg;
break;
case OP_MAX_SIZE:
+   if (scan_scaled(optarg, _size) == -1)
+   err(1, "bad max-size");
+   break;
case OP_MIN_SIZE:
-   /* for now simply ignore */
+   if (scan_scaled(optarg, _size) == -1)
+   err(1, "bad min-size");
break;
case OP_VERSION:
fprintf(stderr, "openrsync: protocol version %u\n",
Index: rsync.1
===
RCS file: /cvs/src/usr.bin/rsync/rsync.1,v
retrieving revision 1.27
diff -u -p -r1.27 rsync.1
--- rsync.1 22 Oct 2021 16:42:28 -  1.27
+++ rsync.1 28 Oct 2021 15:29:42 -
@@ -31,6 +31,8 @@
 .Op Fl -exclude-from Ns = Ns Ar file
 .Op Fl -include Ar pattern
 .Op Fl -include-from Ns = Ns Ar file
+.Op Fl -max-size Ns = Ns size
+.Op Fl -min-size Ns = Ns size
 .Op Fl -no-motd
 .Op Fl -numeric-ids
 .Op Fl -port Ns = Ns Ar service
@@ -127,6 +129,22 @@ set the numeric group ID to match the so
 Also transfer symbolic links.
 The link is transferred as a standalone file: if the destination does
 not 

rpki-client sync output at end of run with output file

2021-10-28 Thread Claudio Jeker
As in $SUBJECT said, sync the output at the end of a rpki-client run with
outputheader() -- the function used to dump this info into the openbgpd
output file.

OK?
-- 
:wq Claudio

Index: main.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.156
diff -u -p -r1.156 main.c
--- main.c  26 Oct 2021 16:59:19 -  1.156
+++ main.c  28 Oct 2021 13:52:27 -
@@ -1173,8 +1173,13 @@ main(int argc, char *argv[])
rc = 1;
 
 
+   logx("Processing time %lld seconds (%lld seconds user, "
+   "%lld seconds system)", stats.elapsed_time.tv_sec,
+   stats.user_time.tv_sec, stats.system_time.tv_sec);
logx("Route Origin Authorizations: %zu (%zu failed parse, %zu invalid)",
stats.roas, stats.roas_fail, stats.roas_invalid);
+   logx("BGPsec Router Certificates: %zu (%zu invalid)",
+   stats.brks, stats.brks_invalids);
logx("Certificates: %zu (%zu failed parse, %zu invalid)",
stats.certs, stats.certs_fail, stats.certs_invalid);
logx("Trust Anchor Locators: %zu", stats.tals);
@@ -1182,8 +1187,6 @@ main(int argc, char *argv[])
stats.mfts, stats.mfts_fail, stats.mfts_stale);
logx("Certificate revocation lists: %zu", stats.crls);
logx("Ghostbuster records: %zu", stats.gbrs);
-   logx("BGPsec Router Certificates: %zu (%zu invalid)",
-   stats.brks, stats.brks_invalids);
logx("Repositories: %zu", stats.repos);
logx("Cleanup: removed %zu files, %zu directories",
stats.del_files, stats.del_dirs);



Re: rpki-client sync output at end of run with output file

2021-10-28 Thread Claudio Jeker
On Thu, Oct 28, 2021 at 08:27:40PM +0200, Theo Buehler wrote:
> On Thu, Oct 28, 2021 at 08:21:12PM +0200, Claudio Jeker wrote:
> > As in $SUBJECT said, sync the output at the end of a rpki-client run with
> > outputheader() -- the function used to dump this info into the openbgpd
> > output file.
> > 
> > OK?
> > -- 
> > :wq Claudio
> > 
> > Index: main.c
> > ===
> > RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
> > retrieving revision 1.156
> > diff -u -p -r1.156 main.c
> > --- main.c  26 Oct 2021 16:59:19 -  1.156
> > +++ main.c  28 Oct 2021 13:52:27 -
> > @@ -1173,8 +1173,13 @@ main(int argc, char *argv[])
> > rc = 1;
> >  
> >  
> > +   logx("Processing time %lld seconds (%lld seconds user, "
> > +   "%lld seconds system)", stats.elapsed_time.tv_sec,
> > +   stats.user_time.tv_sec, stats.system_time.tv_sec);
> 
> This needs (long long) casts for -portable on systems with 32 bit time_t
> (the other output functions also have them).
> 
> otherwise ok
> 

Indeed, will fix and then commit.

-- 
:wq Claudio



remove more BIO from rpki-client part 2

2021-10-26 Thread Claudio Jeker
This switches the cert parser to use d2i_X509 instead of the BIO versions.

-- 
:wq Claudio

Index: cert.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.40
diff -u -p -r1.40 cert.c
--- cert.c  23 Oct 2021 16:06:04 -  1.40
+++ cert.c  26 Oct 2021 11:32:12 -
@@ -976,7 +976,8 @@ out:
  * is also dereferenced.
  */
 static struct cert *
-cert_parse_inner(X509 **xp, const char *fn, int ta)
+cert_parse_inner(X509 **xp, const char *fn, const unsigned char *der,
+size_t len, int ta)
 {
int  rc = 0, extsz, c;
int  sia_present = 0;
@@ -985,28 +986,19 @@ cert_parse_inner(X509 **xp, const char *
X509_EXTENSION  *ext = NULL;
ASN1_OBJECT *obj;
struct parse p;
-   BIO *bio = NULL;
-   FILE*f;
 
*xp = NULL;
 
-   if ((f = fopen(fn, "rb")) == NULL) {
-   warn("%s", fn);
+   /* just fail for empty buffers, the warning was printed elsewhere */
+   if (der == NULL)
return NULL;
-   }
-
-   if ((bio = BIO_new_fp(f, BIO_CLOSE)) == NULL) {
-   if (verbose > 0)
-   cryptowarnx("%s: BIO_new_file", fn);
-   return NULL;
-   }
 
memset(, 0, sizeof(struct parse));
p.fn = fn;
if ((p.res = calloc(1, sizeof(struct cert))) == NULL)
err(1, NULL);
 
-   if ((x = *xp = d2i_X509_bio(bio, NULL)) == NULL) {
+   if ((x = *xp = d2i_X509(NULL, , len)) == NULL) {
cryptowarnx("%s: d2i_X509_bio", p.fn);
goto out;
}
@@ -1144,7 +1136,6 @@ cert_parse_inner(X509 **xp, const char *
 
rc = 1;
 out:
-   BIO_free_all(bio);
if (rc == 0) {
cert_free(p.res);
X509_free(x);
@@ -1154,19 +1145,20 @@ out:
 }
 
 struct cert *
-cert_parse(X509 **xp, const char *fn)
+cert_parse(X509 **xp, const char *fn, const unsigned char *der, size_t len)
 {
-   return cert_parse_inner(xp, fn, 0);
+   return cert_parse_inner(xp, fn, der, len, 0);
 }
 
 struct cert *
-ta_parse(X509 **xp, const char *fn, const unsigned char *pkey, size_t pkeysz)
+ta_parse(X509 **xp, const char *fn, const unsigned char *der, size_t len,
+const unsigned char *pkey, size_t pkeysz)
 {
EVP_PKEY*pk = NULL, *opk = NULL;
struct cert *p;
int  rc = 0;
 
-   if ((p = cert_parse_inner(xp, fn, 1)) == NULL)
+   if ((p = cert_parse_inner(xp, fn, der, len, 1)) == NULL)
return NULL;
 
if (pkey != NULL) {
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.78
diff -u -p -r1.78 extern.h
--- extern.h26 Oct 2021 10:52:49 -  1.78
+++ extern.h26 Oct 2021 10:58:44 -
@@ -403,8 +403,10 @@ struct tal *tal_read(struct ibuf *);
 
 voidcert_buffer(struct ibuf *, const struct cert *);
 voidcert_free(struct cert *);
-struct cert*cert_parse(X509 **, const char *);
-struct cert*ta_parse(X509 **, const char *, const unsigned char *, size_t);
+struct cert*cert_parse(X509 **, const char *, const unsigned char *,
+   size_t);
+struct cert*ta_parse(X509 **, const char *, const unsigned char *, size_t,
+   const unsigned char *, size_t);
 struct cert*cert_read(struct ibuf *);
 voidcert_insert_brks(struct brk_tree *, struct cert *);
 
Index: parser.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.18
diff -u -p -r1.18 parser.c
--- parser.c26 Oct 2021 10:52:50 -  1.18
+++ parser.c26 Oct 2021 10:59:06 -
@@ -191,7 +191,8 @@ proc_parser_mft(struct entity *entp, con
  * parse failure.
  */
 static struct cert *
-proc_parser_cert(const struct entity *entp)
+proc_parser_cert(const struct entity *entp, const unsigned char *der,
+size_t len)
 {
struct cert *cert;
X509*x509;
@@ -204,7 +205,7 @@ proc_parser_cert(const struct entity *en
 
/* Extract certificate data and X509. */
 
-   cert = cert_parse(, entp->file);
+   cert = cert_parse(, entp->file, der, len);
if (cert == NULL)
return NULL;
 
@@ -282,7 +283,8 @@ proc_parser_cert(const struct entity *en
  * parse failure.
  */
 static struct cert *
-proc_parser_root_cert(const struct entity *entp)
+proc_parser_root_cert(const struct entity *entp, const unsigned char *der,
+size_t len)
 {
charsubject[256];
ASN1_TIME   *notBefore, *notAfter;
@@ -296,7 +298,7 @@ proc_parser_root_cert(const struct entit
 
/* Extract certificate data and X509. */
 
-   cert = ta_parse(, entp->file, 

Re: simplify sys___thrsigdivert a bit

2021-10-23 Thread Claudio Jeker
On Sat, Oct 23, 2021 at 05:47:58PM +0200, Mark Kettenis wrote:
> > Date: Sat, 23 Oct 2021 17:29:36 +0200
> > From: Claudio Jeker 
> > 
> > The sys___thrsigdivert code can be simplified a bit. It is possible to
> > set the error before the loop and then have the loop exit after polling
> > for pending signals. IMO the results looks nicer than what we have now.
> > 
> > OK?
> 
> That does not look right:
> 
>   The function sigtimedwait() behaves the same as sigwaitinfo() except
>   that if none of the signals specified by set are pending,
>   sigtimedwait() waits for the time interval specified in the timespec
>   structure referenced by timeout. If the timespec structure pointed
>   to by timeout is zero-valued and if none of the signals specified by
>   set are pending, then sigtimedwait() returns immediately with an
>   error. If timeout is the NULL pointer, the behaviour is unspecified.
> 
> So you need to check for signals first.

The code does the check first. It just sets the error before doing the
pending signal check. If a signal is pending the error is reset to 0 and
the function returns. Else it will break out of the loop with the error
and not hit the tsleep.
 
> The current code looks fine to me.
> 
> 
> > Index: kern/kern_sig.c
> > ===
> > RCS file: /cvs/src/sys/kern/kern_sig.c,v
> > retrieving revision 1.286
> > diff -u -p -r1.286 kern_sig.c
> > --- kern/kern_sig.c 23 Oct 2021 14:56:55 -  1.286
> > +++ kern/kern_sig.c 23 Oct 2021 15:15:21 -
> > @@ -1761,7 +1761,6 @@ sys___thrsigdivert(struct proc *p, void 
> > sigset_t mask = SCARG(uap, sigmask) &~ sigcantmask;
> > siginfo_t si;
> > uint64_t nsecs = INFSLP;
> > -   int timeinvalid = 0;
> > int error = 0;
> >  
> > memset(, 0, sizeof(si));
> > @@ -1774,12 +1773,21 @@ sys___thrsigdivert(struct proc *p, void 
> > if (KTRPOINT(p, KTR_STRUCT))
> > ktrreltimespec(p, );
> >  #endif
> > -   if (!timespecisvalid())
> > -   timeinvalid = 1;
> > -   else
> > +   if (timespecisvalid()) {
> > nsecs = TIMESPEC_TO_NSEC();
> > +   } else {
> > +   /*
> > +* per-POSIX, delay this error until
> > +* after checking for signals
> > +*/
> > +   error = EINVAL;
> > +   }
> > }
> >  
> > +   /* per-POSIX, return immediatly if timeout is zero-valued */
> > +   if (nsecs == 0)
> > +   error = EAGAIN;
> > +
> > dosigsuspend(p, p->p_sigmask &~ mask);
> > for (;;) {
> > si.si_signo = cursig(p);
> > @@ -1791,13 +1799,6 @@ sys___thrsigdivert(struct proc *p, void 
> > break;
> > }
> > }
> > -
> > -   /* per-POSIX, delay this error until after the above */
> > -   if (timeinvalid)
> > -   error = EINVAL;
> > -   /* per-POSIX, return immediatly if timeout is zero-valued */
> > -   if (nsecs == 0)
> > -   error = EAGAIN;
> >  
> > if (error != 0)
> > break;
> > 
> > 

-- 
:wq Claudio



Re: sppp(4)/pppoe(4) - DNS configuration via resolvd(8)

2021-11-08 Thread Claudio Jeker
On Mon, Nov 08, 2021 at 11:52:52AM +0100, Bjorn Ketelaars wrote:
> Diff below does two things:
> 1. add PPP IPCP extensions for name server addresses (rfc1877) to
>sppp(4)
> 2. propose negotiated name servers from sppp(4) to resolvd(8) using
>RTM_PROPOSAL_STATIC route messages.
> 
> With this I'm able to use DNS servers as provided by my ISP who uses
> PPPoE. resolv.conf is updated by resolvd(8) as function of status
> changes of pppoe(4).
> 
> rfc1877 implementation is derived from code from NetBSD, and inspired by
> [0] and [1]. Borrowed code from umb(4) for the route messages.
> 
> Opinions/comments/OK?
> 
> 
> [0] https://marc.info/?l=openbsd-tech=134943767022961=2
> [1] https://marc.info/?l=openbsd-tech=159405677416423=2
> 
> 
> diff --git sys/net/if_sppp.h sys/net/if_sppp.h
> index ff559fcc369..f2dab61e46b 100644
> --- sys/net/if_sppp.h
> +++ sys/net/if_sppp.h
> @@ -132,6 +132,8 @@ struct sipcp {
> * original one here, in network byte order */
>   u_int32_t req_hisaddr;  /* remote address requested (IPv4) */
>   u_int32_t req_myaddr;   /* local address requested (IPv4) */
> +#define IPCP_MAX_DNSSRV  2
> + u_int32_t dns[IPCP_MAX_DNSSRV]; /* IPv4  DNS servers (RFC 1877) */

I would very much prefer to use struct in_addr here (or maybe in_addr_t).
It makes it more clear what the data is.

>  #ifdef INET6
>   struct in6_aliasreq req_ifid;   /* local ifid requested (IPv6) */
>  #endif
> diff --git sys/net/if_spppsubr.c sys/net/if_spppsubr.c
> index ac1dc9a709d..225ad8f5a3e 100644
> --- sys/net/if_spppsubr.c
> +++ sys/net/if_spppsubr.c
> @@ -132,6 +132,10 @@
>  #define IPCP_OPT_ADDRESSES   1   /* both IP addresses; deprecated */
>  #define IPCP_OPT_COMPRESSION 2   /* IP compression protocol (VJ) */
>  #define IPCP_OPT_ADDRESS 3   /* local IP address */
> +#define IPCP_OPT_PRIMDNS 129 /* primary remote dns address */
> +#define _IPCP_OPT_PRIMDNS_   4   /* set/check option */
> +#define IPCP_OPT_SECDNS  131 /* secondary remote dns address 
> */
> +#define _IPCP_OPT_SECDNS_5   /* set/check option */

As kn@ noted this underscore version is a bit rough.
I wonder if IPCP_OPT definitions (from the standard) should be decoupled
from the bitmask values to enable/disable a feature.

  
>  #define IPV6CP_OPT_IFID  1   /* interface identifier */
>  #define IPV6CP_OPT_COMPRESSION   2   /* IPv6 compression protocol */
> @@ -338,6 +342,8 @@ void sppp_update_gw(struct ifnet *ifp);
>  void sppp_set_ip_addrs(void *);
>  void sppp_clear_ip_addrs(void *);
>  void sppp_set_phase(struct sppp *sp);
> +void sppp_update_dns(struct ifnet *ifp);
> +void sppp_rtrequest(struct ifnet *ifp, int req, struct rtentry *rt);
>  
>  /* our control protocol descriptors */
>  static const struct cp lcp = {
> @@ -701,6 +707,7 @@ sppp_attach(struct ifnet *ifp)
>  
>   sp->pp_if.if_type = IFT_PPP;
>   sp->pp_if.if_output = sppp_output;
> + sp->pp_if.if_rtrequest = sppp_rtrequest;
>   ifq_set_maxlen(>pp_if.if_snd, 50);
>   mq_init(>pp_cpq, 50, IPL_NET);
>   sp->pp_loopcnt = 0;
> @@ -2519,6 +2526,12 @@ sppp_ipcp_RCN_rej(struct sppp *sp, struct lcp_header 
> *h, int len)
>   sp->ipcp.opts &= ~(1 << IPCP_OPT_COMPRESS);
>   break;
>  #endif
> + case IPCP_OPT_PRIMDNS:
> + sp->ipcp.opts &= ~(1 << _IPCP_OPT_PRIMDNS_);
> + break;
> + case IPCP_OPT_SECDNS:
> + sp->ipcp.opts &= ~(1 << _IPCP_OPT_SECDNS_);
> + break;
>   }
>   }
>   if (debug)
> @@ -2584,6 +2597,16 @@ sppp_ipcp_RCN_nak(struct sppp *sp, struct lcp_header 
> *h, int len)
>*/
>   break;
>  #endif
> + case IPCP_OPT_PRIMDNS:
> + if (len >= 6 && p[1] == 6)
> + sp->ipcp.dns[0] = p[2] << 24 | p[3] << 16 |
> + p[4] << 8 | p[5];

Please use memcpy and here. Since this remains in network byte order it
should just work.

> + break;
> + case IPCP_OPT_SECDNS:
> + if (len >= 6 && p[1] == 6)
> + sp->ipcp.dns[1] = p[2] << 24 | p[3] << 16 |
> + p[4] << 8 | p[5];

See above.

> + break;
>   }
>   }
>   if (debug)
> @@ -2612,6 +2635,7 @@ sppp_ipcp_tls(struct sppp *sp)
>   IPCP_MYADDR_DYN|IPCP_HISADDR_DYN);
>   sp->ipcp.req_myaddr = 0;
>   sp->ipcp.req_hisaddr = 0;
> + memset(>ipcp.dns, 0, sizeof sp->ipcp.dns);
>  
>   sppp_get_ip_addrs(sp, , , 0);
>   /*
> @@ -2644,6 +2668,10 @@ sppp_ipcp_tls(struct sppp *sp)
>   sp->ipcp.flags |= IPCP_HISADDR_DYN;
>   }
>  
> + /* negotiate name server addresses */
> + sp->ipcp.opts |= (1 << _IPCP_OPT_PRIMDNS_);
> + 

rpki-client ip_addr_print cleanup

2021-11-09 Thread Claudio Jeker
ip_addr_print() can be simplified. ip4_addr2str() and ip6_addr2str() are
the same apart from the different AF argument to inet_ntop(). Just collaps
all into ip_addr_print().

-- 
:wq Claudio

Index: ip.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/ip.c,v
retrieving revision 1.19
diff -u -p -r1.19 ip.c
--- ip.c5 Nov 2021 10:50:41 -   1.19
+++ ip.c9 Nov 2021 15:16:57 -
@@ -234,41 +234,6 @@ ip_addr_parse(const ASN1_BIT_STRING *p,
 }
 
 /*
- * Convert the IPv4 address into CIDR notation conforming to RFC 4632.
- * Buffer should be able to hold xxx.yyy.zzz.www/nn.
- */
-static void
-ip4_addr2str(const struct ip_addr *addr, char *b, size_t bsz)
-{
-   char buf[16];
-   int ret;
-
-   if (inet_ntop(AF_INET, addr->addr, buf, sizeof(buf)) == NULL)
-   err(1, "inet_ntop");
-   ret = snprintf(b, bsz, "%s/%hhu", buf, addr->prefixlen);
-   if (ret < 0 || (size_t)ret >= bsz)
-   err(1, "malformed IPV4 address");
-}
-
-/*
- * Convert the IPv6 address into CIDR notation conforming to RFC 4291.
- * See also RFC 5952.
- * Must hold :::::::/nn.
- */
-static void
-ip6_addr2str(const struct ip_addr *addr, char *b, size_t bsz)
-{
-   char buf[44];
-   int ret;
-
-   if (inet_ntop(AF_INET6, addr->addr, buf, sizeof(buf)) == NULL)
-   err(1, "inet_ntop");
-   ret = snprintf(b, bsz, "%s/%hhu", buf, addr->prefixlen);
-   if (ret < 0 || (size_t)ret >= bsz)
-   err(1, "malformed IPV6 address");
-}
-
-/*
  * Convert a ip_addr into a NUL-terminated CIDR notation string
  * conforming to RFC 4632 or 4291.
  * The size of the buffer must be at least 64 (inclusive).
@@ -277,11 +242,17 @@ void
 ip_addr_print(const struct ip_addr *addr,
 enum afi afi, char *buf, size_t bufsz)
 {
+   char ipbuf[44];
+   int ret, af = AF_INET;
+
+   if (afi == AFI_IPV6)
+   af = AF_INET6;
 
-   if (afi == AFI_IPV4)
-   ip4_addr2str(addr, buf, bufsz);
-   else
-   ip6_addr2str(addr, buf, bufsz);
+   if (inet_ntop(af, addr->addr, ipbuf, sizeof(ipbuf)) == NULL)
+   err(1, "inet_ntop");
+   ret = snprintf(buf, bufsz, "%s/%hhu", ipbuf, addr->prefixlen);
+   if (ret < 0 || (size_t)ret >= bufsz)
+   err(1, "malformed IP address");
 }
 
 /*



rpki-client sync http escape handling with ftp(1)

2021-11-09 Thread Claudio Jeker
kn@ removed '~' from unsafe_chars but also changed the code at the same
time. This tries to bring the version in rpki-client back in sync with the
code in ftp(1).

-- 
:wq Claudio

Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.49
diff -u -p -r1.49 http.c
--- http.c  9 Nov 2021 11:00:43 -   1.49
+++ http.c  9 Nov 2021 18:49:27 -
@@ -211,14 +211,17 @@ http_info(const char *uri)
 }
 
 /*
- * Determine whether the character needs encoding, per RFC1738:
- * - No corresponding graphic US-ASCII.
- * - Unsafe characters.
+ * Determine whether the character needs encoding, per RFC2396.
  */
 static int
-unsafe_char(const char *c0)
+to_encode(const char *c0)
 {
-   const char *unsafe_chars = " <>\"#{}|\\^~[]`";
+   /* 2.4.3. Excluded US-ASCII Characters */
+   const char *excluded_chars =
+   " " /* space */
+   "<>#\"" /* delims (modulo "%", see below) */
+   "{}|\\^[]`" /* unwise */
+   ;
const unsigned char *c = (const unsigned char *)c0;
 
/*
@@ -228,16 +231,15 @@ unsafe_char(const char *c0)
return (iscntrl(*c) || !isascii(*c) ||
 
/*
-* Unsafe characters.
-* '%' is also unsafe, if is not followed by two
+* '%' is also reserved, if is not followed by two
 * hexadecimal digits.
 */
-   strchr(unsafe_chars, *c) != NULL ||
+   strchr(excluded_chars, *c) != NULL ||
(*c == '%' && (!isxdigit(c[1]) || !isxdigit(c[2];
 }
 
 /*
- * Encode given URL, per RFC1738.
+ * Encode given URL, per RFC2396.
  * Allocate and return string to the caller.
  */
 static char *
@@ -254,7 +256,7 @@ url_encode(const char *path)
 * final URL.
 */
for (i = 0; i < length; i++)
-   if (unsafe_char(path + i))
+   if (to_encode(path + i))
new_length += 2;
 
epath = epathp = malloc(new_length + 1);/* One more for '\0'. */
@@ -266,7 +268,7 @@ url_encode(const char *path)
 * Encode, and copy final URL.
 */
for (i = 0; i < length; i++)
-   if (unsafe_char(path + i)) {
+   if (to_encode(path + i)) {
snprintf(epathp, 4, "%%" "%02x",
(unsigned char)path[i]);
epathp += 3;



Re: rpki-client ip_addr_print cleanup

2021-11-09 Thread Claudio Jeker
On Tue, Nov 09, 2021 at 07:44:41PM +0100, Claudio Jeker wrote:
> ip_addr_print() can be simplified. ip4_addr2str() and ip6_addr2str() are
> the same apart from the different AF argument to inet_ntop(). Just collaps
> all into ip_addr_print().

This version is using a switch statement and fails hard for unknown AFIs.
Suggested by Theo.

-- 
:wq Claudio

Index: ip.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/ip.c,v
retrieving revision 1.19
diff -u -p -r1.19 ip.c
--- ip.c5 Nov 2021 10:50:41 -   1.19
+++ ip.c9 Nov 2021 18:59:34 -
@@ -234,41 +234,6 @@ ip_addr_parse(const ASN1_BIT_STRING *p,
 }
 
 /*
- * Convert the IPv4 address into CIDR notation conforming to RFC 4632.
- * Buffer should be able to hold xxx.yyy.zzz.www/nn.
- */
-static void
-ip4_addr2str(const struct ip_addr *addr, char *b, size_t bsz)
-{
-   char buf[16];
-   int ret;
-
-   if (inet_ntop(AF_INET, addr->addr, buf, sizeof(buf)) == NULL)
-   err(1, "inet_ntop");
-   ret = snprintf(b, bsz, "%s/%hhu", buf, addr->prefixlen);
-   if (ret < 0 || (size_t)ret >= bsz)
-   err(1, "malformed IPV4 address");
-}
-
-/*
- * Convert the IPv6 address into CIDR notation conforming to RFC 4291.
- * See also RFC 5952.
- * Must hold :::::::/nn.
- */
-static void
-ip6_addr2str(const struct ip_addr *addr, char *b, size_t bsz)
-{
-   char buf[44];
-   int ret;
-
-   if (inet_ntop(AF_INET6, addr->addr, buf, sizeof(buf)) == NULL)
-   err(1, "inet_ntop");
-   ret = snprintf(b, bsz, "%s/%hhu", buf, addr->prefixlen);
-   if (ret < 0 || (size_t)ret >= bsz)
-   err(1, "malformed IPV6 address");
-}
-
-/*
  * Convert a ip_addr into a NUL-terminated CIDR notation string
  * conforming to RFC 4632 or 4291.
  * The size of the buffer must be at least 64 (inclusive).
@@ -277,11 +242,25 @@ void
 ip_addr_print(const struct ip_addr *addr,
 enum afi afi, char *buf, size_t bufsz)
 {
+   char ipbuf[44];
+   int ret, af;
+
+   switch (afi) {
+   case AFI_IPV4:
+   af = AF_INET;
+   break;
+   case AFI_IPV6:
+   af = AF_INET6;
+   break;
+   default:
+   errx(1, "unsupported address family identifier");
+   }
 
-   if (afi == AFI_IPV4)
-   ip4_addr2str(addr, buf, bufsz);
-   else
-   ip6_addr2str(addr, buf, bufsz);
+   if (inet_ntop(af, addr->addr, ipbuf, sizeof(ipbuf)) == NULL)
+   err(1, "inet_ntop");
+   ret = snprintf(buf, bufsz, "%s/%hhu", ipbuf, addr->prefixlen);
+   if (ret < 0 || (size_t)ret >= bufsz)
+   err(1, "malformed IP address");
 }
 
 /*



Re: rpki-client better exit behaviour when something goes wrong

2021-11-04 Thread Claudio Jeker
On Thu, Nov 04, 2021 at 11:27:46AM -0600, Theo de Raadt wrote:
> Claudio Jeker  wrote:
> 
> > This diff replaces the errx() call in the poll fd check with warnings plus
> > an exit of the main event loop. It also prints an error in case not all
> > files have been processed.
> > 
> > An example after kill -9 of the rsync process is:
> > rpki-client: https://rrdp.lacnic.net/rrdp/notification.xml: loaded from 
> > network
> > rpki-client: poll[1]: hangup
> > rpki-client: rsync terminated signal 9
> 
> I am not thrilled with giving people error messages about a system call 
> (poll).
> 
> In this specific case, the actual issue is on the next like (it is a rsync
> failure, which you caused I suspect)
> 
> Is that 2nd message not enough?
> 
> Could you set hangup = 1, but skip the warnx, so that the code just reacts
> correctly?
> 
> Are there other circumstances (different types of fd), which do not make
> it to a wait (rrdp?).  Can those report a nice termination message?
> 

I agree that the hangup message is not very helpful. It is actually 
the one message I did not alter. I'm happy to remove that message.
For the errors from msgbuf_write() I think those are valid error messages
and I feel the POLLERR|POLLNVAL fall into the same boat.

Updated diff below
-- 
:wq Claudio

Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.48
diff -u -p -r1.48 http.c
--- http.c  4 Nov 2021 14:24:41 -   1.48
+++ http.c  4 Nov 2021 14:25:03 -
@@ -159,7 +159,7 @@ static uint8_t *tls_ca_mem;
 static size_t tls_ca_size;
 
 /* HTTP request API */
-static voidhttp_req_new(size_t, char *, char *, int);
+static voidhttp_req_new(size_t, char *, char *, int, int);
 static voidhttp_req_free(struct http_request *);
 static voidhttp_req_done(size_t, enum http_result, const char *);
 static voidhttp_req_fail(size_t);
@@ -507,7 +507,7 @@ http_resolv(struct addrinfo **res, const
  * Create and queue a new request.
  */
 static void
-http_req_new(size_t id, char *uri, char *modified_since, int outfd)
+http_req_new(size_t id, char *uri, char *modified_since, int count, int outfd)
 {
struct http_request *req;
char *host, *port, *path;
@@ -530,6 +530,7 @@ http_req_new(size_t id, char *uri, char 
req->path = path;
req->uri = uri;
req->modified_since = modified_since;
+   req->redirect_loop = count;
 
TAILQ_INSERT_TAIL(, req, entry);
 }
@@ -1135,7 +1136,8 @@ http_redirect(struct http_connection *co
err(1, NULL);
 
logx("redirect to %s", http_info(uri));
-   http_req_new(conn->req->id, uri, mod_since, outfd); 
+   http_req_new(conn->req->id, uri, mod_since, conn->req->redirect_loop,
+   outfd); 
 
/* clear request before moving connection to idle */
http_req_free(conn->req);
@@ -1867,7 +1869,7 @@ proc_http(char *bind_addr, int fd)
io_read_str(b, );
 
/* queue up new requests */
-   http_req_new(id, uri, mod, b->fd);
+   http_req_new(id, uri, mod, 0, b->fd);
ibuf_free(b);
}
}
Index: main.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.162
diff -u -p -r1.162 main.c
--- main.c  4 Nov 2021 14:24:41 -   1.162
+++ main.c  4 Nov 2021 17:42:42 -
@@ -1020,19 +1020,23 @@ main(int argc, char *argv[])
}
 
for (i = 0; i < NPFD; i++) {
-   if (pfd[i].revents & (POLLERR|POLLNVAL))
-   errx(1, "poll[%zu]: bad fd", i);
-   if (pfd[i].revents & POLLHUP) {
-   warnx("poll[%zu]: hangup", i);
+   if (pfd[i].revents & (POLLERR|POLLNVAL)) {
+   warnx("poll[%zu]: bad fd", i);
hangup = 1;
}
+   if (pfd[i].revents & POLLHUP)
+   hangup = 1;
if (pfd[i].revents & POLLOUT) {
switch (msgbuf_write(queues[i])) {
case 0:
-   errx(1, "write[%zu]: "
+   warnx("write[%zu]: "
"connection closed", i);
+   hangup = 1;
+

rpki-client X509_free XXX fix

2021-11-04 Thread Claudio Jeker
There is this bit in parser.c
X509_free(x509); // needed? XXX

As tb@ properly noted this X509_free() is needed because the cert_parse()
returns an up referenced x509 pointer back.

I moved the X509_free() so the error cases become simpler and we no longer
leak a reference on success. At least this is how I read the code.

OK?
-- 
:wq Claudio

Index: parser.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/parser.c,v
retrieving revision 1.27
diff -u -p -r1.27 parser.c
--- parser.c4 Nov 2021 11:32:55 -   1.27
+++ parser.c4 Nov 2021 17:25:18 -
@@ -232,12 +232,12 @@ proc_parser_cert(const struct entity *en
X509_STORE_CTX_cleanup(ctx);
sk_X509_free(chain);
sk_X509_CRL_free(crls);
+   X509_free(x509);
 
cert->talid = a->cert->talid;
 
/* Validate the cert to get the parent */
if (!valid_cert(entp->file, , cert)) {
-   X509_free(x509); // needed? XXX
cert_free(cert);
return NULL;
}
@@ -247,7 +247,6 @@ proc_parser_cert(const struct entity *en
 */
if (cert->purpose == CERT_PURPOSE_CA) {
if (!auth_insert(, cert, a)) {
-   X509_free(x509); // needed? XXX
cert_free(cert);
return NULL;
}
@@ -318,20 +317,22 @@ proc_parser_root_cert(const struct entit
goto badcert;
}
 
+   X509_free(x509);
+
cert->talid = entp->talid;
 
/*
 * Add valid roots to the RPKI auth tree.
 */
if (!auth_insert(, cert, NULL)) {
-   X509_free(x509); // needed? XXX
cert_free(cert);
return NULL;
}
 
return cert;
+
  badcert:
-   X509_free(x509); // needed? XXX
+   X509_free(x509);
cert_free(cert);
return NULL;
 }



Re: rpki-client show attr name in rrdp parse errors

2021-11-05 Thread Claudio Jeker
On Wed, Nov 03, 2021 at 12:58:17PM +0100, Claudio Jeker wrote:
> In one place this is already done but this makes sure we show the bad
> attribute in all cases where a non conforming attribute is found.

Found another bunch of those non conforming attribute errors. Adjust them
as well.

OK?
-- 
:wq Claudio

Index: rrdp_notification.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/rrdp_notification.c,v
retrieving revision 1.9
diff -u -p -r1.9 rrdp_notification.c
--- rrdp_notification.c 29 Oct 2021 09:27:36 -  1.9
+++ rrdp_notification.c 5 Nov 2021 14:06:18 -
@@ -141,7 +141,7 @@ start_notification_elem(struct notificat
continue;
}
PARSE_FAIL(p, "parse failed - non conforming "
-   "attribute found in notification elem");
+   "attribute '%s' found in notification elem", attr[i]);
}
if (!(has_xmlns && nxml->version && nxml->session_id && nxml->serial))
PARSE_FAIL(p, "parse failed - incomplete "
@@ -185,7 +185,7 @@ start_snapshot_elem(struct notification_
continue;
}
PARSE_FAIL(p, "parse failed - non conforming "
-   "attribute found in snapshot elem");
+   "attribute '%s' found in snapshot elem", attr[i]);
}
if (hasUri != 1 || hasHash != 1)
PARSE_FAIL(p, "parse failed - incomplete snapshot attributes");
@@ -239,7 +239,7 @@ start_delta_elem(struct notification_xml
continue;
}
PARSE_FAIL(p, "parse failed - non conforming "
-   "attribute found in snapshot elem");
+   "attribute '%s' found in snapshot elem", attr[i]);
}
/* Only add to the list if we are relevant */
if (hasUri != 1 || hasHash != 1 || delta_serial == 0)



speedup io marshal in rpki-client

2021-11-05 Thread Claudio Jeker
Noticed the other day. The ip addr arrays and as number array are
marshalled element by element which is not very efficent.
All the data is in one big blob of memory so just use the basic io
operations for a memory blob and ship the full array at once.

This seems to reduce runtime by 5-10% (in my unscientific testing).
Also it makes the code a fair bit simpler.
-- 
:wq Claudio

Index: cert.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.46
diff -u -p -r1.46 cert.c
--- cert.c  4 Nov 2021 11:32:55 -   1.46
+++ cert.c  5 Nov 2021 07:53:50 -
@@ -1225,34 +1225,6 @@ cert_free(struct cert *p)
free(p);
 }
 
-static void
-cert_ip_buffer(struct ibuf *b, const struct cert_ip *p)
-{
-   io_simple_buffer(b, >afi, sizeof(enum afi));
-   io_simple_buffer(b, >type, sizeof(enum cert_ip_type));
-
-   if (p->type != CERT_IP_INHERIT) {
-   io_simple_buffer(b, >min, sizeof(p->min));
-   io_simple_buffer(b, >max, sizeof(p->max));
-   }
-
-   if (p->type == CERT_IP_RANGE)
-   ip_addr_range_buffer(b, >range);
-   else if (p->type == CERT_IP_ADDR)
-   ip_addr_buffer(b, >ip);
-}
-
-static void
-cert_as_buffer(struct ibuf *b, const struct cert_as *p)
-{
-   io_simple_buffer(b, >type, sizeof(enum cert_as_type));
-   if (p->type == CERT_AS_RANGE) {
-   io_simple_buffer(b, >range.min, sizeof(uint32_t));
-   io_simple_buffer(b, >range.max, sizeof(uint32_t));
-   } else if (p->type == CERT_AS_ID)
-   io_simple_buffer(b, >id, sizeof(uint32_t));
-}
-
 /*
  * Write certificate parsed content into buffer.
  * See cert_read() for the other side of the pipe.
@@ -1260,18 +1232,15 @@ cert_as_buffer(struct ibuf *b, const str
 void
 cert_buffer(struct ibuf *b, const struct cert *p)
 {
-   size_t   i;
-
io_simple_buffer(b, >expires, sizeof(p->expires));
io_simple_buffer(b, >purpose, sizeof(p->purpose));
io_simple_buffer(b, >talid, sizeof(p->talid));
io_simple_buffer(b, >ipsz, sizeof(p->ipsz));
-   for (i = 0; i < p->ipsz; i++)
-   cert_ip_buffer(b, >ips[i]);
-
io_simple_buffer(b, >asz, sizeof(p->asz));
-   for (i = 0; i < p->asz; i++)
-   cert_as_buffer(b, >as[i]);
+
+   io_simple_buffer(b, p->ips, p->ipsz * sizeof(p->ips[0]));
+   io_simple_buffer(b, p->as, p->asz * sizeof(p->as[0]));
+
io_str_buffer(b, p->mft);
io_str_buffer(b, p->notify);
io_str_buffer(b, p->repo);
@@ -1282,34 +1251,6 @@ cert_buffer(struct ibuf *b, const struct
io_str_buffer(b, p->pubkey);
 }
 
-static void
-cert_ip_read(struct ibuf *b, struct cert_ip *p)
-{
-   io_read_buf(b, >afi, sizeof(enum afi));
-   io_read_buf(b, >type, sizeof(enum cert_ip_type));
-
-   if (p->type != CERT_IP_INHERIT) {
-   io_read_buf(b, >min, sizeof(p->min));
-   io_read_buf(b, >max, sizeof(p->max));
-   }
-
-   if (p->type == CERT_IP_RANGE)
-   ip_addr_range_read(b, >range);
-   else if (p->type == CERT_IP_ADDR)
-   ip_addr_read(b, >ip);
-}
-
-static void
-cert_as_read(struct ibuf *b, struct cert_as *p)
-{
-   io_read_buf(b, >type, sizeof(enum cert_as_type));
-   if (p->type == CERT_AS_RANGE) {
-   io_read_buf(b, >range.min, sizeof(uint32_t));
-   io_read_buf(b, >range.max, sizeof(uint32_t));
-   } else if (p->type == CERT_AS_ID)
-   io_read_buf(b, >id, sizeof(uint32_t));
-}
-
 /*
  * Allocate and read parsed certificate content from descriptor.
  * The pointer must be freed with cert_free().
@@ -1319,7 +1260,6 @@ struct cert *
 cert_read(struct ibuf *b)
 {
struct cert *p;
-   size_t   i;
 
if ((p = calloc(1, sizeof(struct cert))) == NULL)
err(1, NULL);
@@ -1328,19 +1268,17 @@ cert_read(struct ibuf *b)
io_read_buf(b, >purpose, sizeof(p->purpose));
io_read_buf(b, >talid, sizeof(p->talid));
io_read_buf(b, >ipsz, sizeof(p->ipsz));
+   io_read_buf(b, >asz, sizeof(p->asz));
 
p->ips = calloc(p->ipsz, sizeof(struct cert_ip));
if (p->ips == NULL)
err(1, NULL);
-   for (i = 0; i < p->ipsz; i++)
-   cert_ip_read(b, >ips[i]);
+   io_read_buf(b, p->ips, p->ipsz * sizeof(p->ips[0]));
 
-   io_read_buf(b, >asz, sizeof(p->asz));
p->as = calloc(p->asz, sizeof(struct cert_as));
if (p->as == NULL)
err(1, NULL);
-   for (i = 0; i < p->asz; i++)
-   cert_as_read(b, >as[i]);
+   io_read_buf(b, p->as, p->asz * sizeof(p->as[0]));
 
io_read_str(b, >mft);
io_read_str(b, >notify);
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.93
diff -u -p -r1.93 

rpki-client better exit behaviour when something goes wrong

2021-11-04 Thread Claudio Jeker
This diff replaces the errx() call in the poll fd check with warnings plus
an exit of the main event loop. It also prints an error in case not all
files have been processed.

An example after kill -9 of the rsync process is:
rpki-client: https://rrdp.lacnic.net/rrdp/notification.xml: loaded from network
rpki-client: poll[1]: hangup
rpki-client: rsync terminated signal 9
rpki-client: not all files processed, giving up

I find this better.
-- 
:wq Claudio

Index: main.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/main.c,v
retrieving revision 1.162
diff -u -p -r1.162 main.c
--- main.c  4 Nov 2021 14:24:41 -   1.162
+++ main.c  4 Nov 2021 17:12:27 -
@@ -1020,8 +1020,10 @@ main(int argc, char *argv[])
}
 
for (i = 0; i < NPFD; i++) {
-   if (pfd[i].revents & (POLLERR|POLLNVAL))
-   errx(1, "poll[%zu]: bad fd", i);
+   if (pfd[i].revents & (POLLERR|POLLNVAL)) {
+   warnx("poll[%zu]: bad fd", i);
+   hangup = 1;
+   }
if (pfd[i].revents & POLLHUP) {
warnx("poll[%zu]: hangup", i);
hangup = 1;
@@ -1029,10 +1031,14 @@ main(int argc, char *argv[])
if (pfd[i].revents & POLLOUT) {
switch (msgbuf_write(queues[i])) {
case 0:
-   errx(1, "write[%zu]: "
+   warnx("write[%zu]: "
"connection closed", i);
+   hangup = 1;
+   break;
case -1:
-   err(1, "write[%zu]", i);
+   warnx("write[%zu]", i);
+   hangup = 1;
+   break;
}
}
}
@@ -1147,7 +1153,7 @@ main(int argc, char *argv[])
 
/* processing did not finish because of error */
if (entity_queue != 0)
-   return 1;
+   errx(1, "not all files processed, giving up");
 
logx("all files parsed: generating output");
 



rpki-client fix chunked encoding for larger then 32k chunks

2021-11-03 Thread Claudio Jeker
Noticed by accident. The chunked encoding only works for chunks smaller
than 32k (the HTTP internal read buffer). For chunks bigger than 32k the
state machine jumps too early (after the first write of 32k) into the
STATE_RESPONSE_CHUNKED_TRAILER state and so everything gets confused.

Fix is simple. Check in data_write() that for chunked encoding iosz is
null before switching to STATE_RESPONSE_CHUNKED_TRAILER.
-- 
:wq Claudio

Index: http.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.46
diff -u -p -r1.46 http.c
--- http.c  29 Oct 2021 08:51:20 -  1.46
+++ http.c  3 Nov 2021 11:39:16 -
@@ -1679,7 +1679,7 @@ data_write(struct http_connection *conn)
 
/* all data written, switch back to read */
if (conn->bufpos == 0 || conn->iosz == 0) {
-   if (conn->chunked)
+   if (conn->chunked && conn->iosz == 0)
conn->state = STATE_RESPONSE_CHUNKED_TRAILER;
else
conn->state = STATE_RESPONSE_DATA;



rpki-client limit number of concurrent rsyncs

2021-11-03 Thread Claudio Jeker
Don't become a fork bomb. Limit the number of processes by stopping to
poll for new jobs once the limit is reached. I set the limit to 16 which
is larger then the biggest concurrency I have seen during fetches.

OK?
-- 
:wq Claudio

Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.89
diff -u -p -r1.89 extern.h
--- extern.h3 Nov 2021 10:50:18 -   1.89
+++ extern.h3 Nov 2021 14:25:53 -
@@ -618,4 +618,7 @@ int mkpath(const char *);
 /* Maximum depth of the RPKI tree. */
 #defineMAX_CERT_DEPTH  12
 
+/* Maximum number of concurrent rsync processes. */
+#define MAX_RSYNC_PROCESSES 16
+
 #endif /* ! EXTERN_H */
Index: rsync.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/rsync.c,v
retrieving revision 1.29
diff -u -p -r1.29 rsync.c
--- rsync.c 28 Oct 2021 13:50:29 -  1.29
+++ rsync.c 3 Nov 2021 14:25:00 -
@@ -119,7 +119,7 @@ proc_child(int signal)
 void
 proc_rsync(char *prog, char *bind_addr, int fd)
 {
-   size_t   i, idsz = 0;
+   size_t   i, idsz = 0, nprocs = 0;
int  rc = 0;
struct pollfdpfd;
struct msgbufmsgq;
@@ -186,7 +186,9 @@ proc_rsync(char *prog, char *bind_addr, 
pid_t pid;
int st;
 
-   pfd.events = POLLIN;
+   pfd.events = 0;
+   if (nprocs < MAX_RSYNC_PROCESSES)
+   pfd.events |= POLLIN;
if (msgq.queued)
pfd.events |= POLLOUT;
 
@@ -228,6 +230,7 @@ proc_rsync(char *prog, char *bind_addr, 
ids[i].uri = NULL;
ids[i].pid = 0;
ids[i].id = 0;
+   nprocs--;
}
if (pid == -1 && errno != ECHILD)
err(1, "waitpid");
@@ -314,6 +317,7 @@ proc_rsync(char *prog, char *bind_addr, 
ids[i].id = id;
ids[i].pid = pid;
ids[i].uri = uri;
+   nprocs++;
 
/* Clean up temporary values. */
 



rpki-client show attr name in rrdp parse errors

2021-11-03 Thread Claudio Jeker
In one place this is already done but this makes sure we show the bad
attribute in all cases where a non conforming attribute is found.

OK?
-- 
:wq Claudio

Index: rrdp_delta.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/rrdp_delta.c,v
retrieving revision 1.4
diff -u -p -r1.4 rrdp_delta.c
--- rrdp_delta.c28 Oct 2021 11:57:00 -  1.4
+++ rrdp_delta.c3 Nov 2021 11:52:42 -
@@ -87,7 +87,7 @@ start_delta_elem(struct delta_xml *dxml,
continue;
}
PARSE_FAIL(p, "parse failed - non conforming "
-   "attribute found in delta elem");
+   "attribute '%s' found in delta elem", attr[i]);
}
if (!(has_xmlns && dxml->version && dxml->session_id && dxml->serial))
PARSE_FAIL(p, "parse failed - incomplete delta attributes");
@@ -136,7 +136,7 @@ start_publish_withdraw_elem(struct delta
continue;
}
PARSE_FAIL(p, "parse failed - non conforming "
-   "attribute found in publish/withdraw elem");
+   "attribute '%s' found in publish/withdraw elem", attr[i]);
}
if (hasUri != 1)
PARSE_FAIL(p,
Index: rrdp_snapshot.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/rrdp_snapshot.c,v
retrieving revision 1.3
diff -u -p -r1.3 rrdp_snapshot.c
--- rrdp_snapshot.c 28 Oct 2021 11:57:00 -  1.3
+++ rrdp_snapshot.c 3 Nov 2021 11:51:45 -
@@ -80,7 +80,7 @@ start_snapshot_elem(struct snapshot_xml 
}
PARSE_FAIL(p,
"parse failed - non conforming "
-   "attribute found in snapshot elem");
+   "attribute '%s' found in snapshot elem", attr[i]);
}
if (!(has_xmlns && sxml->version && sxml->session_id && sxml->serial))
PARSE_FAIL(p,



Re: rpki-client fix CRLF handling in tal parser

2021-11-03 Thread Claudio Jeker
On Wed, Nov 03, 2021 at 06:48:51PM +0100, Theo Buehler wrote:
> On Wed, Nov 03, 2021 at 06:34:05PM +0100, Claudio Jeker wrote:
> > Fix CRLF handling by properly setting nl to the right NUL byte.
> > In the CRLF case both \r\n are replaced by \0 and so the code
> > needs to adjust the nl pointer else valid_url() and the check for .cer
> > endings fail.
> 
> It feels odd to interrupt CRLF handling by advancing the buffer to the
> next line.
> 
> How about this?

Much better. OK claudio@
 
> Index: tal.c
> ===
> RCS file: /cvs/src/usr.sbin/rpki-client/tal.c,v
> retrieving revision 1.32
> diff -u -p -r1.32 tal.c
> --- tal.c 26 Oct 2021 16:12:54 -  1.32
> +++ tal.c 3 Nov 2021 17:47:40 -
> @@ -58,14 +58,16 @@ tal_parse_buffer(const char *fn, char *b
>   while ((nl = memchr(buf, '\n', len)) != NULL) {
>   line = buf;
>  
> - /* replace LF and optional CR with NUL */
> - *nl = '\0';
> - if (nl > line && nl[-1] == '\r')
> - nl[-1] = '\0';
> -
>   /* advance buffer to next line */
>   len -= nl + 1 - buf;
>   buf = nl + 1;
> +
> + /* replace LF and optional CR with NUL, point nl at first NUL */
> + *nl = '\0';
> + if (nl > line && nl[-1] == '\r') {
> + nl[-1] = '\0';
> + nl--;
> + }
>  
>   if (optcomment) {
>   /* if this is a comment, just eat the line */
> 

-- 
:wq Claudio



rpki-client refactor tal handling

2021-11-03 Thread Claudio Jeker
This diff changes how the certs and roa track the tal that covers them.
Instead of passing strings around use ids and a simple lookup table
for the description. This will make it possible to add tal ids to more
things.

Usual test run works and the output for openbgpd and json look sane.
-- 
:wq Claudio

Index: cert.c
===
RCS file: /cvs/src/usr.sbin/rpki-client/cert.c,v
retrieving revision 1.45
diff -u -p -r1.45 cert.c
--- cert.c  2 Nov 2021 19:30:30 -   1.45
+++ cert.c  3 Nov 2021 17:45:36 -
@@ -1220,7 +1220,6 @@ cert_free(struct cert *p)
free(p->aia);
free(p->aki);
free(p->ski);
-   free(p->tal);
free(p->pubkey);
X509_free(p->x509);
free(p);
@@ -1265,6 +1264,7 @@ cert_buffer(struct ibuf *b, const struct
 
io_simple_buffer(b, >expires, sizeof(time_t));
io_simple_buffer(b, >purpose, sizeof(enum cert_purpose));
+   io_simple_buffer(b, >talid, sizeof(size_t));
io_simple_buffer(b, >ipsz, sizeof(size_t));
for (i = 0; i < p->ipsz; i++)
cert_ip_buffer(b, >ips[i]);
@@ -1279,7 +1279,6 @@ cert_buffer(struct ibuf *b, const struct
io_str_buffer(b, p->aia);
io_str_buffer(b, p->aki);
io_str_buffer(b, p->ski);
-   io_str_buffer(b, p->tal);
io_str_buffer(b, p->pubkey);
 }
 
@@ -1327,6 +1326,7 @@ cert_read(struct ibuf *b)
 
io_read_buf(b, >expires, sizeof(time_t));
io_read_buf(b, >purpose, sizeof(enum cert_purpose));
+   io_read_buf(b, >talid, sizeof(size_t));
io_read_buf(b, >ipsz, sizeof(size_t));
 
p->ips = calloc(p->ipsz, sizeof(struct cert_ip));
@@ -1349,7 +1349,6 @@ cert_read(struct ibuf *b)
io_read_str(b, >aia);
io_read_str(b, >aki);
io_read_str(b, >ski);
-   io_read_str(b, >tal);
io_read_str(b, >pubkey);
 
assert(p->mft != NULL || p->purpose == CERT_PURPOSE_BGPSEC_ROUTER);
@@ -1406,8 +1405,7 @@ insert_brk(struct brk_tree *tree, struct
 
b->asid = asid;
b->expires = cert->expires;
-   if ((b->tal = strdup(cert->tal)) == NULL)
-   err(1, NULL);
+   b->talid = cert->talid;
if ((b->ski = strdup(cert->ski)) == NULL)
err(1, NULL);
if ((b->pubkey = strdup(cert->pubkey)) == NULL)
@@ -1420,13 +1418,10 @@ insert_brk(struct brk_tree *tree, struct
if ((found = RB_INSERT(brk_tree, tree, b)) != NULL) {
if (found->expires < b->expires) {
found->expires = b->expires;
-   free(found->tal);
-   found->tal = b->tal;
-   b->tal = NULL;
+   found->talid = b->talid;
}
free(b->ski);
free(b->pubkey);
-   free(b->tal);
free(b);
}
 }
Index: extern.h
===
RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v
retrieving revision 1.89
diff -u -p -r1.89 extern.h
--- extern.h3 Nov 2021 10:50:18 -   1.89
+++ extern.h3 Nov 2021 17:58:11 -
@@ -118,6 +118,7 @@ struct cert {
size_t   ipsz; /* length of "ips" */
struct cert_as  *as; /* list of AS numbers and ranges */
size_t   asz; /* length of "asz" */
+   size_t   talid; /* cert is covered by which TAL */
char*repo; /* CA repository (rsync:// uri) */
char*mft; /* manifest (rsync:// uri) */
char*notify; /* RRDP notify (https:// uri) */
@@ -125,8 +126,7 @@ struct cert {
char*aia; /* AIA (or NULL, for trust anchor) */
char*aki; /* AKI (or NULL, for trust anchor) */
char*ski; /* SKI */
-   char*tal; /* basename of TAL for this cert */
-   enum cert_purposepurpose; /* Certificate Purpose (BGPSec or CA) 
*/
+   enum cert_purposepurpose; /* BGPSec or CA */
char*pubkey; /* Subject Public Key Info */
X509*x509; /* the cert */
time_t   expires; /* do not use after */
@@ -145,6 +145,7 @@ struct tal {
unsigned char   *pkey; /* DER-encoded public key */
size_t   pkeysz; /* length of pkey */
char*descr; /* basename of tal file */
+   size_t   id;
 };
 
 /*
@@ -192,11 +193,11 @@ struct roa {
uint32_t asid; /* asID of ROA (if 0, RFC 6483 sec 4) */
struct roa_ip   *ips; /* IP prefixes */
size_t   ipsz; /* number of IP prefixes */
+   size_t  talid; /* ROAs are covered by which TAL */
int  valid; /* validated resources */
char*aia; /* AIA */
char*aki; /* AKI */
char*ski; /* SKI */
-   char*tal; /* 

<    10   11   12   13   14   15   16   17   18   19   >