Re: acme-client(1): dns-01

2020-12-24 Thread Theo de Raadt
Daniel Moch  wrote:

> I like being able to specify a user to run the script as.  In my case
> it's sufficient to run the script as 'nobody'.

Regarding this second sentence: never use nobody for another purpose.
It has other purposes, and if people follow this pattern of using nobody
then potentially even more things will "share" the uid, creating risks.

Create a new user, if you must.



Re: acme-client(1): dns-01

2020-12-24 Thread Daniel Moch
Quoth Florian Obser :
> Comments, tests?

Works as advertized.  Tested against Vultr DNS.

When generating a star cert, the config parser requires the starred
name(s) be quoted.  The error in this situation is a bit vague, just a
reference to a syntax error on the line IIRC.  Not sure if that can be
addressed, but I thought I'd mention it, especially since the config
in /etc/examples doesn't quote these.

I like being able to specify a user to run the script as.  In my case
it's sufficient to run the script as 'nobody'.

These scripts end up being called hooks in other, similar utilities.
Maybe you could replace "exec" with "hook," or "hook exec" if you want
to keep it semi-grammatical.

Thanks!

-- 
Daniel Moch
https://djmo.ch



IPsec IPv6 PMTU

2020-12-24 Thread Alexander Bluhm
Hi,

This diff makes path MTU discovery work for IPv6 IPsec ESP over
IPv4 tunnel.  Basically it ports code from v4 to v6.

It also makes v4 and v6 code look simmilar.  If you want, I can
split this for easier review.

ok?

bluhm

Index: netinet/icmp6.h
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/icmp6.h,v
retrieving revision 1.50
diff -u -p -r1.50 icmp6.h
--- netinet/icmp6.h 28 Oct 2020 17:27:35 -  1.50
+++ netinet/icmp6.h 22 Dec 2020 17:05:39 -
@@ -599,6 +599,7 @@ void icmp6_prepare(struct mbuf *);
 voidicmp6_redirect_input(struct mbuf *, int);
 voidicmp6_redirect_output(struct mbuf *, struct rtentry *);
 int icmp6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
+struct rtentry *icmp6_mtudisc_clone(struct sockaddr_in6 *, u_int, int);
 
 struct ip6ctlparam;
 void   icmp6_mtudisc_update(struct ip6ctlparam *, int);
Index: netinet/ip_input.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.352
diff -u -p -r1.352 ip_input.c
--- netinet/ip_input.c  16 Nov 2020 06:44:38 -  1.352
+++ netinet/ip_input.c  22 Dec 2020 17:05:39 -
@@ -1418,8 +1418,8 @@ ip_forward(struct mbuf *m, struct ifnet 
goto freecopy;
}
 
+   memset(, 0, sizeof(ro));
sin = satosin(_dst);
-   memset(sin, 0, sizeof(*sin));
sin->sin_family = AF_INET;
sin->sin_len = sizeof(*sin);
sin->sin_addr = ip->ip_dst;
@@ -1429,6 +1429,7 @@ ip_forward(struct mbuf *m, struct ifnet 
rt = rtalloc_mpath(sintosa(sin), >ip_src.s_addr,
m->m_pkthdr.ph_rtableid);
if (rt == NULL) {
+   ipstat_inc(ips_noroute);
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0);
return;
}
Index: netinet/ip_ipsp.h
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipsp.h,v
retrieving revision 1.196
diff -u -p -r1.196 ip_ipsp.h
--- netinet/ip_ipsp.h   5 Nov 2020 19:28:28 -   1.196
+++ netinet/ip_ipsp.h   22 Dec 2020 17:05:39 -
@@ -610,6 +610,7 @@ voidesp4_ctlinput(int, struct sockaddr 
 
 #ifdef INET6
 intesp6_input(struct mbuf **, int *, int, int);
+void   esp6_ctlinput(int, struct sockaddr *, u_int, void *);
 #endif /* INET6 */
 
 /* XF_IPCOMP */
Index: netinet/ip_output.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.358
diff -u -p -r1.358 ip_output.c
--- netinet/ip_output.c 20 Dec 2020 21:15:47 -  1.358
+++ netinet/ip_output.c 22 Dec 2020 17:05:39 -
@@ -612,7 +612,7 @@ ip_output_ipsec_send(struct tdb *tdb, st
ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned));
if (rt != NULL) {
rt->rt_mtu = tdb->tdb_mtu;
-   if (ro && ro->ro_rt != NULL) {
+   if (ro != NULL && ro->ro_rt != NULL) {
rtfree(ro->ro_rt);
ro->ro_rt = rtalloc(>ro_dst, RT_RESOLVE,
m->m_pkthdr.ph_rtableid);
Index: netinet/ipsec_input.c
===
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ipsec_input.c,v
retrieving revision 1.173
diff -u -p -r1.173 ipsec_input.c
--- netinet/ipsec_input.c   1 Sep 2020 01:53:34 -   1.173
+++ netinet/ipsec_input.c   24 Dec 2020 19:22:09 -
@@ -66,6 +66,7 @@
 #ifdef INET6
 #include 
 #include 
+#include 
 #include 
 #include 
 #endif /* INET6 */
@@ -83,6 +84,7 @@
 #include "bpfilter.h"
 
 void ipsec_common_ctlinput(u_int, int, struct sockaddr *, void *, int);
+void ipsec6_common_ctlinput(u_int, int, struct sockaddr *, void *, int);
 
 #ifdef ENCDEBUG
 #define DPRINTF(x) if (encdebug) printf x
@@ -946,18 +948,43 @@ ipcomp4_input(struct mbuf **mp, int *off
 }
 
 void
+ipsec_set_mtu(struct tdb *tdbp, u_int32_t mtu, uint64_t timeout,
+const char *msg)
+{
+   ssize_t adjust;
+
+   if (timeout == 0)
+   timeout = ip_mtudisc_timeout;
+   /* Walk the chain backwards to the first tdb */
+   NET_ASSERT_LOCKED();
+   for (; tdbp; tdbp = tdbp->tdb_inext) {
+   if (tdbp->tdb_flags & TDBF_INVALID ||
+   (adjust = ipsec_hdrsz(tdbp)) == -1)
+   return;
+
+   mtu -= adjust;
+
+   /* Store adjusted MTU in tdb */
+   tdbp->tdb_mtu = mtu;
+   tdbp->tdb_mtutimeout = gettime() + timeout;
+   DPRINTF(("%s: %s: spi %08x mtu %d adjust %ld timeout %llu\n",
+   __func__, msg, ntohl(tdbp->tdb_spi), 

acme-client(1): dns-01

2020-12-24 Thread Florian Obser
'tis the season to be jolly...

I think it's time to kick the tires on this one.

I don't like the "exec" keyword, we should find something better.
Also, should the user be optional?
Oh, and it's not enforcing that exec is present in the config.

sthen pointed me in the direction of dehydrated
https://github.com/dehydrated-io/dehydrated/blob/master/docs/dns-verification.md
and uacme
https://github.com/ndilieto/uacme
as examples for acme clients that implement hooks for (dns) challenges

I implemented the uacme api since I find that less ugly. It should be
trivial to transmogrify it with a shell one-liner to support
dehydrated.

Comments, tests?

diff --git acme-client.conf.5 acme-client.conf.5
index 3c5fd1c2362..e580a365c51 100644
--- acme-client.conf.5
+++ acme-client.conf.5
@@ -170,11 +170,55 @@ in one file, and is required by most browsers.
 This is optional if
 .Ar domain certificate
 is specified.
-.It Ic sign with Ar authority
+.It Ic sign with Ar authority Op Ic challenge Ar type
 The certificate authority (as declared above in the
 .Sx AUTHORITIES
 section) to use.
 If this setting is absent, the first authority specified is used.
+.Ar type
+can be
+.Cm http
+or
+.Cm dns .
+It defaults to
+.Cm http .
+.It Ic exec Ar script Ic as Ar user
+Run
+.Ar script
+as user
+.Ar user
+for each
+.Cm dns
+challenge.
+This is required when using the
+.Cm dns
+challenge type.
+The script is called with five arguments:
+.Bl -tag -width Ds
+.It Ar method
+.Cm begin ,
+.Cm done ,
+or
+.Cm failed .
+.Cm begin
+indicates that a DNS record should be created and
+.Cm done
+or
+.Cm failed
+indicate that a DNS record should be removed.
+.It Ar type
+.Cm dns-01 .
+.It Ar ident
+The domain.
+.It Ar token
+Unused, for compatibility with existing hook scripts.
+.It Ar auth
+The challenge response.
+.El
+.Pp
+The script needs to create a DNS record of the form
+.Dl _acme-challenge.ident 30 IN TXT auth
+and exit once it has propagated to all name servers.
 .It Ic challengedir Ar path
 The directory in which the challenge file will be stored.
 If it is not specified, a default of
diff --git chngproc.c chngproc.c
index 476daed3416..deef61fccc6 100644
--- chngproc.c
+++ chngproc.c
@@ -15,10 +15,13 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#include 
+
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -26,8 +29,38 @@
 
 #include "extern.h"
 
-int
-chngproc(int netsock, const char *root)
+static int
+do_exec(const char *exec, const char *method, const char *type,
+const char *ident, const char *token, const char *auth)
+{
+   pid_tpid;
+   int  status;
+
+   switch (pid = fork()) {
+   case -1:
+   warn("fork");
+   return -1;
+   case 0: /* child */
+   /* XXX close netproc fd */
+   if (pledge("stdio rpath exec", NULL) == -1) {
+   warn("pledge");
+   return -1;
+   }
+   execl(exec, exec, method, type, ident, token, auth, NULL);
+   warn("execl %s", exec);
+   _exit(1);
+   }
+   if (waitpid(pid, , 0) == -1) {
+   warn("waitpid");
+   return -1;
+   }
+   if (WEXITSTATUS(status) == 0)
+   return 0;
+   return -1;
+}
+
+static int
+chngproc_http(int netsock, const char *root)
 {
char *tok = NULL, *th = NULL, *fmt = NULL, **fs = NULL;
size_ti, fsz = 0;
@@ -153,3 +186,114 @@ out:
free(tok);
return rc;
 }
+
+static int
+chngproc_dns(int netsock, const char* exec, const char *exec_as)
+{
+   struct passwd   *pw;
+   size_t   i, identsz = 0;
+   long lval;
+   int  rc = 0, cc;
+   enum chngop  op;
+   char*ident = NULL, *tok = NULL, *auth = NULL;
+   char**idents = NULL;
+   void*pp;
+
+   if ((pw = getpwnam(exec_as)) == NULL) {
+   warn("getpwnam");
+   goto out;
+   }
+   if (setgroups(1, >pw_gid) ||
+   setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
+   setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) {
+   warnx("can't drop privileges");
+   goto out;
+   }
+
+   if (unveil(exec, "x") == -1) {
+   warn("unveil");
+   goto out;
+   }
+
+   if (pledge("stdio rpath proc exec", NULL) == -1) {
+   warn("pledge");
+   goto out;
+   }
+
+   for (;;) {
+   op = CHNG__MAX;
+   if ((lval = readop(netsock, COMM_CHNG_OP)) == 0)
+   op = CHNG_STOP;
+   else if (lval == CHNG_SYN)
+   op = lval;
+
+   if (op == CHNG__MAX) {
+   warnx("unknown operation from netproc");
+   goto out;
+   } else if 

ftp(1): handle HTTP 308

2020-12-24 Thread Lucas
Hello tech@,

Given that ftp already deals with HTTP 307, I think we can teach it to
deal with HTTP 308 too. HTTP 308 is to HTTP 301 what HTTP 307 is to HTTP
302: Permanently Moved, but doesn't allow to change the HTTP verb.
Definition of HTTP 308 can be found in RFC 7538.

oolong$ ftp -Mo /dev/null http://h.lgv5.net/c/308
Trying 78.47.117.79...
Requesting http://h.lgv5.net/c/308
ftp: Error retrieving http://h.lgv5.net/c/308: 308 Permanent Redirect
oolong$ ./ftp -Mo /dev/null http://h.lgv5.net/c/308
Trying 78.47.117.79...
Requesting http://h.lgv5.net/c/308
Redirected to http://h.lgv5.net/c/200
Trying 78.47.117.79...
Requesting http://h.lgv5.net/c/200
480 bytes received in 0.00 seconds (4.66 MB/s)

Cheers!
-Lucas

Index: fetch.c
===
RCS file: /home/cvs/src/usr.bin/ftp/fetch.c,v
retrieving revision 1.198
diff -u -p -r1.198 fetch.c
--- fetch.c 18 Oct 2020 20:35:18 -  1.198
+++ fetch.c 24 Dec 2020 14:03:03 -
@@ -843,6 +843,7 @@ noslash:
case 302:   /* Found */
case 303:   /* See Other */
case 307:   /* Temporary Redirect */
+   case 308:   /* Permanent Redirect */
isredirect++;
if (redirect_loop++ > 10) {
warnx("Too many redirections requested");



sdhc@acpi improvements

2020-12-24 Thread Mark Kettenis
Some ACPI platforms targetting linux that have quirky SDHC controllers
use ACPI _DSD properties to override the capability register of the
controller.  An example is the SDHC controller on the Raspberry Pi4.

Diff below implements this.

ok?


Index: dev/acpi/sdhc_acpi.c
===
RCS file: /cvs/src/sys/dev/acpi/sdhc_acpi.c,v
retrieving revision 1.15
diff -u -p -r1.15 sdhc_acpi.c
--- dev/acpi/sdhc_acpi.c8 May 2020 11:18:01 -   1.15
+++ dev/acpi/sdhc_acpi.c24 Dec 2020 11:19:35 -
@@ -84,6 +84,7 @@ sdhc_acpi_attach(struct device *parent, 
struct sdhc_acpi_softc *sc = (struct sdhc_acpi_softc *)self;
struct acpi_attach_args *aaa = aux;
struct aml_value res;
+   uint32_t cap, capmask;
 
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_node = aaa->aaa_node;
@@ -140,10 +141,18 @@ sdhc_acpi_attach(struct device *parent, 
sdhc_acpi_power_on(sc, sc->sc_node);
sdhc_acpi_explore(sc);
 
+   cap = acpi_getpropint(sc->sc_node, "sdhci-caps", 0);
+   capmask = acpi_getpropint(sc->sc_node, "sdhci-caps-mask", 0);
+   if (capmask != 0) {
+   cap = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+   SDHC_CAPABILITIES);
+   cap &= ~capmask;
+   }
+
sc->sc.sc_host = >sc_host;
sc->sc.sc_dmat = aaa->aaa_dmat;
sdhc_host_found(>sc, sc->sc_memt, sc->sc_memh,
-   aaa->aaa_size[0], 1, 0);
+   aaa->aaa_size[0], 1, cap);
 }
 
 int




Re: acme-client(1): fulfil all challenges, then tell the the CA

2020-12-24 Thread Florian Obser
On Wed, Dec 23, 2020 at 09:58:41PM +, Stuart Henderson wrote:
> On 2020/12/23 18:09, Florian Obser wrote:
> > First fulfil all challenges then tell the CA that it should check.
> > 
> > With a CSR with multiple SANs acme-client would write one challenge,
> > tell the CA, write the next challenge and so on.
> > 
> > For http-01 this doesn't matter but I think this will be nicer for dns-01
> > because there are propagation delays to consider.
> > 
> > Please be extra careful checking this. If I mess this up people might
> > run into renewal issues months from now. And when that happens people
> > tend to comment... (Which I also pull this out of the big diff I'm
> > currently working on for dns-01.)
> > 
> > OK?
> 
> I tested by forcibly renewing some multi-name certificates. I saw that
> letsencrypt didn't bother re-challenging because they already had a
> recent auth so I moved them to buypass, all looks good. (FWIW I did

Yes, it's a bit annoying that you can't force a revalidation.

Say you fiddle around with your webserver config and want to test if
acme-client still works. Chances are that you won't notice if there is
a problem because let's encrypt just hands you a renewed cert.

Another way to force a revalidation is deleting the account key...

> some ecdsa as well as rsa, not that it matters for this test).

Thanks, one thing I'm worried about is some challenges being valid and
others are pending. (I.e. is the "if() continue" correct, pretty sure
it is since I just pull it down...) But I have no idea how to test
that.

> 
> Reads good and works for me, OK.
> 
> 
> > diff --git netproc.c netproc.c
> > index 38732a4dd01..7c502643acc 100644
> > --- netproc.c
> > +++ netproc.c
> > @@ -840,7 +840,12 @@ netproc(int kfd, int afd, int Cfd, int cfd, int dfd, 
> > int rfd,
> > if (readop(Cfd, COMM_CHNG_ACK) != CHNG_ACK)
> > goto out;
> >  
> > -   /* Write to the CA that it's ready. */
> > +   }
> > +   /* Write to the CA that it's ready. */
> > +   for (i = 0; i < order.authsz; i++) {
> > +   if (chngs[i].status == CHNG_VALID ||
> > +   chngs[i].status == CHNG_INVALID)
> > +   continue;
> > if (!dochngresp(, [i]))
> > goto out;
> > }
> > 
> > 
> > -- 
> > I'm not entirely sure you are real.
> > 
> 

-- 
I'm not entirely sure you are real.