1*5b337cd6Sflorian /* $Id: chngproc.c,v 1.17 2022/05/05 19:51:35 florian Exp $ */
2de579d12Sflorian /*
3de579d12Sflorian * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv>
4de579d12Sflorian *
5de579d12Sflorian * Permission to use, copy, modify, and distribute this software for any
6de579d12Sflorian * purpose with or without fee is hereby granted, provided that the above
7de579d12Sflorian * copyright notice and this permission notice appear in all copies.
8de579d12Sflorian *
9de579d12Sflorian * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
10de579d12Sflorian * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11de579d12Sflorian * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
12de579d12Sflorian * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13de579d12Sflorian * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14de579d12Sflorian * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15de579d12Sflorian * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16de579d12Sflorian */
17de579d12Sflorian
18de579d12Sflorian #include <assert.h>
19*5b337cd6Sflorian #include <ctype.h>
20de579d12Sflorian #include <err.h>
21de579d12Sflorian #include <errno.h>
22de579d12Sflorian #include <fcntl.h>
23de579d12Sflorian #include <stdio.h>
24de579d12Sflorian #include <stdlib.h>
25de579d12Sflorian #include <string.h>
26de579d12Sflorian #include <unistd.h>
27de579d12Sflorian
28de579d12Sflorian #include "extern.h"
29de579d12Sflorian
30de579d12Sflorian int
chngproc(int netsock,const char * root)31383e31e9Sbenno chngproc(int netsock, const char *root)
32de579d12Sflorian {
337bce6888Sderaadt char *tok = NULL, *th = NULL, *fmt = NULL, **fs = NULL;
347bce6888Sderaadt size_t i, fsz = 0;
357bce6888Sderaadt int rc = 0, fd = -1, cc;
36de579d12Sflorian long lval;
37de579d12Sflorian enum chngop op;
38de579d12Sflorian void *pp;
39de579d12Sflorian
4061075b4cSflorian
4161075b4cSflorian if (unveil(root, "wc") == -1) {
42bc5a8259Sbeck warn("unveil %s", root);
43de579d12Sflorian goto out;
44ec0d8c8bSderaadt }
4561075b4cSflorian
46ec0d8c8bSderaadt if (pledge("stdio cpath wpath", NULL) == -1) {
47ec0d8c8bSderaadt warn("pledge");
48de579d12Sflorian goto out;
49ec0d8c8bSderaadt }
50de579d12Sflorian
51de579d12Sflorian /*
52de579d12Sflorian * Loop while we wait to get a thumbprint and token.
53de579d12Sflorian * We'll get this for each SAN request.
54de579d12Sflorian */
55de579d12Sflorian
56de579d12Sflorian for (;;) {
57de579d12Sflorian op = CHNG__MAX;
587cd8f039Sjsing if ((lval = readop(netsock, COMM_CHNG_OP)) == 0)
59de579d12Sflorian op = CHNG_STOP;
607cd8f039Sjsing else if (lval == CHNG_SYN)
61de579d12Sflorian op = lval;
62de579d12Sflorian
634de82fa3Sderaadt if (op == CHNG__MAX) {
64de579d12Sflorian warnx("unknown operation from netproc");
65de579d12Sflorian goto out;
664de82fa3Sderaadt } else if (op == CHNG_STOP)
67de579d12Sflorian break;
68de579d12Sflorian
694de82fa3Sderaadt assert(op == CHNG_SYN);
70de579d12Sflorian
71de579d12Sflorian /*
72de579d12Sflorian * Read the thumbprint and token.
73de579d12Sflorian * The token is the filename, so store that in a vector
74de579d12Sflorian * of tokens that we'll later clean up.
75de579d12Sflorian */
76de579d12Sflorian
777cd8f039Sjsing if ((th = readstr(netsock, COMM_THUMB)) == NULL)
78de579d12Sflorian goto out;
797cd8f039Sjsing else if ((tok = readstr(netsock, COMM_TOK)) == NULL)
80de579d12Sflorian goto out;
81*5b337cd6Sflorian else if (strlen(tok) < 1) {
82*5b337cd6Sflorian warnx("token is too short");
83*5b337cd6Sflorian goto out;
84*5b337cd6Sflorian }
85*5b337cd6Sflorian
86*5b337cd6Sflorian for (i = 0; tok[i]; ++i) {
87*5b337cd6Sflorian int ch = (unsigned char)tok[i];
88*5b337cd6Sflorian if (!isalnum(ch) && ch != '-' && ch != '_') {
89*5b337cd6Sflorian warnx("token is not a valid base64url");
90*5b337cd6Sflorian goto out;
91*5b337cd6Sflorian }
92*5b337cd6Sflorian }
93de579d12Sflorian
9461075b4cSflorian if (asprintf(&fmt, "%s.%s", tok, th) == -1) {
9561075b4cSflorian warn("asprintf");
9661075b4cSflorian goto out;
9761075b4cSflorian }
9861075b4cSflorian
99de579d12Sflorian /* Vector appending... */
100de579d12Sflorian
10182f95fa9Sderaadt pp = reallocarray(fs, (fsz + 1), sizeof(char *));
1027cd8f039Sjsing if (pp == NULL) {
103de579d12Sflorian warn("realloc");
104de579d12Sflorian goto out;
105de579d12Sflorian }
106de579d12Sflorian fs = pp;
10761075b4cSflorian if (asprintf(&fs[fsz], "%s/%s", root, tok) == -1) {
108de579d12Sflorian warn("asprintf");
109de579d12Sflorian goto out;
110de579d12Sflorian }
11161075b4cSflorian fsz++;
11261075b4cSflorian free(tok);
11361075b4cSflorian tok = NULL;
114de579d12Sflorian
115de579d12Sflorian /*
116de579d12Sflorian * Create and write to our challenge file.
117de579d12Sflorian * Note: we use file descriptors instead of FILE
118de579d12Sflorian * because we want to minimise our pledges.
119de579d12Sflorian */
120cb135f92Sbenno fd = open(fs[fsz - 1], O_WRONLY|O_CREAT|O_TRUNC, 0444);
1217cd8f039Sjsing if (fd == -1) {
122de579d12Sflorian warn("%s", fs[fsz - 1]);
123de579d12Sflorian goto out;
124ec13f15cSnaddy }
125ec13f15cSnaddy if (write(fd, fmt, strlen(fmt)) == -1) {
126de579d12Sflorian warn("%s", fs[fsz - 1]);
127de579d12Sflorian goto out;
128ec13f15cSnaddy }
129ec13f15cSnaddy if (close(fd) == -1) {
130de579d12Sflorian warn("%s", fs[fsz - 1]);
131de579d12Sflorian goto out;
132de579d12Sflorian }
133de579d12Sflorian fd = -1;
134de579d12Sflorian
135de579d12Sflorian free(th);
136de579d12Sflorian free(fmt);
137de579d12Sflorian th = fmt = NULL;
138de579d12Sflorian
13961075b4cSflorian dodbg("%s: created", fs[fsz - 1]);
140de579d12Sflorian
141de579d12Sflorian /*
142de579d12Sflorian * Write our acknowledgement.
143de579d12Sflorian * Ignore reader failure.
144de579d12Sflorian */
145de579d12Sflorian
146de579d12Sflorian cc = writeop(netsock, COMM_CHNG_ACK, CHNG_ACK);
1477cd8f039Sjsing if (cc == 0)
148de579d12Sflorian break;
149de579d12Sflorian if (cc < 0)
150de579d12Sflorian goto out;
151de579d12Sflorian }
152de579d12Sflorian
153de579d12Sflorian rc = 1;
154de579d12Sflorian out:
155de579d12Sflorian close(netsock);
1567cd8f039Sjsing if (fd != -1)
157de579d12Sflorian close(fd);
158de579d12Sflorian for (i = 0; i < fsz; i++) {
1597cd8f039Sjsing if (unlink(fs[i]) == -1 && errno != ENOENT)
160de579d12Sflorian warn("%s", fs[i]);
161de579d12Sflorian free(fs[i]);
162de579d12Sflorian }
163de579d12Sflorian free(fs);
164de579d12Sflorian free(fmt);
165de579d12Sflorian free(th);
166de579d12Sflorian free(tok);
16734335c11Sjsing return rc;
168de579d12Sflorian }
169