1 /* $Id: chngproc.c,v 1.16 2021/07/12 15:09:20 beck Exp $ */ 2 /* 3 * Copyright (c) 2016 Kristaps Dzonsons <kristaps@bsd.lv> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <assert.h> 19 #include <err.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 27 #include "extern.h" 28 29 int 30 chngproc(int netsock, const char *root) 31 { 32 char *tok = NULL, *th = NULL, *fmt = NULL, **fs = NULL; 33 size_t i, fsz = 0; 34 int rc = 0, fd = -1, cc; 35 long lval; 36 enum chngop op; 37 void *pp; 38 39 40 if (unveil(root, "wc") == -1) { 41 warn("unveil %s", root); 42 goto out; 43 } 44 45 if (pledge("stdio cpath wpath", NULL) == -1) { 46 warn("pledge"); 47 goto out; 48 } 49 50 /* 51 * Loop while we wait to get a thumbprint and token. 52 * We'll get this for each SAN request. 53 */ 54 55 for (;;) { 56 op = CHNG__MAX; 57 if ((lval = readop(netsock, COMM_CHNG_OP)) == 0) 58 op = CHNG_STOP; 59 else if (lval == CHNG_SYN) 60 op = lval; 61 62 if (op == CHNG__MAX) { 63 warnx("unknown operation from netproc"); 64 goto out; 65 } else if (op == CHNG_STOP) 66 break; 67 68 assert(op == CHNG_SYN); 69 70 /* 71 * Read the thumbprint and token. 72 * The token is the filename, so store that in a vector 73 * of tokens that we'll later clean up. 74 */ 75 76 if ((th = readstr(netsock, COMM_THUMB)) == NULL) 77 goto out; 78 else if ((tok = readstr(netsock, COMM_TOK)) == NULL) 79 goto out; 80 81 if (asprintf(&fmt, "%s.%s", tok, th) == -1) { 82 warn("asprintf"); 83 goto out; 84 } 85 86 /* Vector appending... */ 87 88 pp = reallocarray(fs, (fsz + 1), sizeof(char *)); 89 if (pp == NULL) { 90 warn("realloc"); 91 goto out; 92 } 93 fs = pp; 94 if (asprintf(&fs[fsz], "%s/%s", root, tok) == -1) { 95 warn("asprintf"); 96 goto out; 97 } 98 fsz++; 99 free(tok); 100 tok = NULL; 101 102 /* 103 * Create and write to our challenge file. 104 * Note: we use file descriptors instead of FILE 105 * because we want to minimise our pledges. 106 */ 107 fd = open(fs[fsz - 1], O_WRONLY|O_CREAT|O_TRUNC, 0444); 108 if (fd == -1) { 109 warn("%s", fs[fsz - 1]); 110 goto out; 111 } 112 if (write(fd, fmt, strlen(fmt)) == -1) { 113 warn("%s", fs[fsz - 1]); 114 goto out; 115 } 116 if (close(fd) == -1) { 117 warn("%s", fs[fsz - 1]); 118 goto out; 119 } 120 fd = -1; 121 122 free(th); 123 free(fmt); 124 th = fmt = NULL; 125 126 dodbg("%s: created", fs[fsz - 1]); 127 128 /* 129 * Write our acknowledgement. 130 * Ignore reader failure. 131 */ 132 133 cc = writeop(netsock, COMM_CHNG_ACK, CHNG_ACK); 134 if (cc == 0) 135 break; 136 if (cc < 0) 137 goto out; 138 } 139 140 rc = 1; 141 out: 142 close(netsock); 143 if (fd != -1) 144 close(fd); 145 for (i = 0; i < fsz; i++) { 146 if (unlink(fs[i]) == -1 && errno != ENOENT) 147 warn("%s", fs[i]); 148 free(fs[i]); 149 } 150 free(fs); 151 free(fmt); 152 free(th); 153 free(tok); 154 return rc; 155 } 156