Florian Obser <flor...@openbsd.org> wrote:
> On 2022-05-02 03:04 +0430, Ali Farzanrad <ali_farzan...@riseup.net> wrote:
> > Hi tech@,
> >
> > I know that acme-client is unveiled properly, but isn't it better to
> > check token names?
> 
> Nice catch, the token is untrusted input.
> We should validate this differently though.
> 
> RFC 8555, 8.5 HTTP Challenge:
> 
>    token (required, string):  A random value that uniquely identifies
>       the challenge.  This value MUST have at least 128 bits of entropy.
>       It MUST NOT contain any characters outside the base64url alphabet
>       and MUST NOT include base64 padding characters ("=").
> 
> base64url is defined in
> RFC 4648, 5. Base 64 Encoding with URL and Filename Safe Alphabet
> 
> It's basically isalpha || '-' || '_'.
> 
> Are you up to implementing that check instead?
> 

Hi Florian,

Yes, I read the RFC, it should work, but I couldn't test it yet, because
my domain manager is a little lazy (I've registeret 2 subdomains for my
domain, but it is not listed in name servers yet).  I'll probably test
it tomorrow.

I read the isalnum man page, it said that isalnum might have different
behavior based on locale, so I decide to not use that.  Is it OK?

Index: chngproc.c
===================================================================
RCS file: /cvs/src/usr.sbin/acme-client/chngproc.c,v
retrieving revision 1.16
diff -u -p -r1.16 chngproc.c
--- chngproc.c  12 Jul 2021 15:09:20 -0000      1.16
+++ chngproc.c  3 May 2022 13:03:45 -0000
@@ -26,6 +26,8 @@
 
 #include "extern.h"
 
+static int      is_base64url(const char *);
+
 int
 chngproc(int netsock, const char *root)
 {
@@ -77,6 +79,10 @@ chngproc(int netsock, const char *root)
                        goto out;
                else if ((tok = readstr(netsock, COMM_TOK)) == NULL)
                        goto out;
+               else if (!is_base64url(tok)) {
+                       warnx("token is not base64url");
+                       goto out;
+               }
 
                if (asprintf(&fmt, "%s.%s", tok, th) == -1) {
                        warn("asprintf");
@@ -152,4 +158,24 @@ out:
        free(th);
        free(tok);
        return rc;
+}
+
+static int
+is_base64url(const char *s)
+{
+       for (; *s; ++s) {
+               int ch = (unsigned char)*s;
+               if ((ch >= '0' && ch <= '9') ||
+                   (ch >= 'A' && ch <= 'Z') ||
+                   (ch >= 'a' && ch <= 'z'))
+                       continue;
+               switch (ch) {
+               case '-':
+               case '_':
+                       break;
+               default:
+                       return 0;
+               }
+       }
+       return 1;
 }

Reply via email to