File: [local] / src / usr.sbin / acme-client / chngproc.c (download)
Revision 1.17, Thu May 5 19:51:35 2022 UTC (2 years, 1 month ago) by florian
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, HEAD Changes since 1.16: +14 -1 lines
Check that the challenge token which is turned into a filename is
base64url encoded.
We have only the challenge directory unveil(2)'ed so funny business
like ../ will not work, but we shouldn't generate garbage filenames
that someone else might trip over either.
Pointed out and diff by Ali Farzanrad (ali_farzanrad AT riseup.net)
OK beck
|
/* $Id: chngproc.c,v 1.17 2022/05/05 19:51:35 florian Exp $ */
/*
* Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv>
*
* 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 AUTHORS DISCLAIM ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS 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 <assert.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "extern.h"
int
chngproc(int netsock, const char *root)
{
char *tok = NULL, *th = NULL, *fmt = NULL, **fs = NULL;
size_t i, fsz = 0;
int rc = 0, fd = -1, cc;
long lval;
enum chngop op;
void *pp;
if (unveil(root, "wc") == -1) {
warn("unveil %s", root);
goto out;
}
if (pledge("stdio cpath wpath", NULL) == -1) {
warn("pledge");
goto out;
}
/*
* Loop while we wait to get a thumbprint and token.
* We'll get this for each SAN request.
*/
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 (op == CHNG_STOP)
break;
assert(op == CHNG_SYN);
/*
* Read the thumbprint and token.
* The token is the filename, so store that in a vector
* of tokens that we'll later clean up.
*/
if ((th = readstr(netsock, COMM_THUMB)) == NULL)
goto out;
else if ((tok = readstr(netsock, COMM_TOK)) == NULL)
goto out;
else if (strlen(tok) < 1) {
warnx("token is too short");
goto out;
}
for (i = 0; tok[i]; ++i) {
int ch = (unsigned char)tok[i];
if (!isalnum(ch) && ch != '-' && ch != '_') {
warnx("token is not a valid base64url");
goto out;
}
}
if (asprintf(&fmt, "%s.%s", tok, th) == -1) {
warn("asprintf");
goto out;
}
/* Vector appending... */
pp = reallocarray(fs, (fsz + 1), sizeof(char *));
if (pp == NULL) {
warn("realloc");
goto out;
}
fs = pp;
if (asprintf(&fs[fsz], "%s/%s", root, tok) == -1) {
warn("asprintf");
goto out;
}
fsz++;
free(tok);
tok = NULL;
/*
* Create and write to our challenge file.
* Note: we use file descriptors instead of FILE
* because we want to minimise our pledges.
*/
fd = open(fs[fsz - 1], O_WRONLY|O_CREAT|O_TRUNC, 0444);
if (fd == -1) {
warn("%s", fs[fsz - 1]);
goto out;
}
if (write(fd, fmt, strlen(fmt)) == -1) {
warn("%s", fs[fsz - 1]);
goto out;
}
if (close(fd) == -1) {
warn("%s", fs[fsz - 1]);
goto out;
}
fd = -1;
free(th);
free(fmt);
th = fmt = NULL;
dodbg("%s: created", fs[fsz - 1]);
/*
* Write our acknowledgement.
* Ignore reader failure.
*/
cc = writeop(netsock, COMM_CHNG_ACK, CHNG_ACK);
if (cc == 0)
break;
if (cc < 0)
goto out;
}
rc = 1;
out:
close(netsock);
if (fd != -1)
close(fd);
for (i = 0; i < fsz; i++) {
if (unlink(fs[i]) == -1 && errno != ENOENT)
warn("%s", fs[i]);
free(fs[i]);
}
free(fs);
free(fmt);
free(th);
free(tok);
return rc;
}