diff options
author | Henning Brauer <henning@cvs.openbsd.org> | 2004-05-04 12:52:06 +0000 |
---|---|---|
committer | Henning Brauer <henning@cvs.openbsd.org> | 2004-05-04 12:52:06 +0000 |
commit | ac1ddc2c99c6c92aa30be01bb5a0ea9b5c12dda9 (patch) | |
tree | ffc1e9db8fa5dcd3d585abc750224dfd0b404d62 /sbin/dhclient/privsep.c | |
parent | 2daf03fc192c6120be9db3e0262049bb69a67354 (diff) |
privilege seperate dhclient.
the privileged child's duty is the dhclient-script env setup & exection.
the parent process now chroots to /var/empty and drops privileges to _dhcp
mostly hacked at vancouver airport
with some feedback from krw@ and otto@, tested to not break installs by krw@
Diffstat (limited to 'sbin/dhclient/privsep.c')
-rw-r--r-- | sbin/dhclient/privsep.c | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/sbin/dhclient/privsep.c b/sbin/dhclient/privsep.c new file mode 100644 index 00000000000..aa7efddf9db --- /dev/null +++ b/sbin/dhclient/privsep.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2004 Henning Brauer <henning@openbsd.org> + * + * 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 AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "dhcpd.h" +#include "privsep.h" + +struct buf * +buf_open(size_t len) +{ + struct buf *buf; + + if ((buf = calloc(1, sizeof(struct buf))) == NULL) + return (NULL); + if ((buf->buf = malloc(len)) == NULL) { + free(buf); + return (NULL); + } + buf->size = len; + + return (buf); +} + +int +buf_add(struct buf *buf, void *data, size_t len) +{ + if (buf->wpos + len > buf->size) + return (-1); + + memcpy(buf->buf + buf->wpos, data, len); + buf->wpos += len; + return (0); +} + +int +buf_close(int sock, struct buf *buf) +{ + ssize_t n; + + do { + n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos); + if (n != -1) + buf->rpos += n; + if (n == 0) { /* connection closed */ + errno = 0; + return (-1); + } + } while (n == -1 && (errno == EAGAIN || errno == EINTR)); + + if (buf->rpos < buf->size) + error("short write: wanted %u got %d bytes", buf->size, + buf->rpos); + + return (n); +} + +ssize_t +buf_read(int sock, void *buf, size_t nbytes) +{ + ssize_t n, r = 0; + + do { + n = read(sock, buf, nbytes); + if (n == 0) + error("connection closed"); + if (n != -1) { + r += n; + buf += n; + nbytes -= n; + } + } while (n == -1 && (errno == EINTR || errno == EAGAIN)); + + if (n == -1) + error("buf_read: %m"); + + if (r < nbytes) + error("short read: wanted %u got %d bytes", nbytes, r); + + return (r); +} + +void +dispatch_imsg(int fd) +{ + struct imsg_hdr hdr; + char *medium, *reason, *filename, + *servername, *prefix; + size_t medium_len, reason_len, filename_len, + servername_len, prefix_len, totlen; + struct client_lease lease; + int ret, i, optlen; + struct buf *buf; + + buf_read(fd, &hdr, sizeof(hdr)); + + switch (hdr.code) { + case IMSG_SCRIPT_INIT: + if (hdr.len < sizeof(hdr) + sizeof(size_t)) + error("corrupted message received"); + buf_read(fd, &medium_len, sizeof(medium_len)); + if (hdr.len < medium_len + sizeof(size_t) + sizeof(hdr) + + sizeof(size_t)) + error("corrupted message received"); + if (medium_len > 0) { + if ((medium = calloc(1, medium_len + 1)) == NULL) + error("%m"); + buf_read(fd, medium, medium_len); + } else + medium = NULL; + + buf_read(fd, &reason_len, sizeof(reason_len)); + if (hdr.len < medium_len + reason_len + sizeof(hdr)) + error("corrupted message received"); + if (reason_len > 0) { + if ((reason = calloc(1, reason_len + 1)) == NULL) + error("%m"); + buf_read(fd, reason, reason_len); + } else + reason = NULL; + + priv_script_init(reason, medium); + free(reason); + free(medium); + break; + case IMSG_SCRIPT_WRITE_PARAMS: + totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t); + if (hdr.len < totlen) + error("corrupted message received"); + buf_read(fd, &lease, sizeof(lease)); + + buf_read(fd, &filename_len, sizeof(filename_len)); + totlen += filename_len + sizeof(size_t); + if (hdr.len < totlen) + error("corrupted message received"); + if (filename_len > 0) { + if ((filename = calloc(1, filename_len + 1)) == NULL) + error("%m"); + buf_read(fd, filename, filename_len); + } else + filename = NULL; + + buf_read(fd, &servername_len, sizeof(servername_len)); + totlen += servername_len + sizeof(size_t); + if (hdr.len < totlen) + error("corrupted message received"); + if (servername_len > 0) { + if ((servername = + calloc(1, servername_len + 1)) == NULL) + error("%m"); + buf_read(fd, servername, servername_len); + } else + servername = NULL; + + buf_read(fd, &prefix_len, sizeof(prefix_len)); + totlen += prefix_len; + if (hdr.len < totlen) + error("corrupted message received"); + if (prefix_len > 0) { + if ((prefix = calloc(1, prefix_len + 1)) == NULL) + error("%m"); + buf_read(fd, prefix, prefix_len); + } else + prefix = NULL; + + for (i = 0; i < 256; i++) { + totlen += sizeof(optlen); + if (hdr.len < totlen) + error("corrupted message received"); + buf_read(fd, &optlen, sizeof(optlen)); + lease.options[i].data = NULL; + lease.options[i].len = optlen; + if (optlen > 0) { + totlen += optlen; + if (hdr.len < totlen) + error("corrupted message received"); + lease.options[i].data = + calloc(1, optlen + 1); + if (lease.options[i].data == NULL) + error("%m"); + buf_read(fd, lease.options[i].data, optlen); + } + } + lease.server_name = servername; + lease.filename = filename; + + priv_script_write_params(prefix, &lease); + + free(servername); + free(filename); + free(prefix); + for (i = 0; i < 256; i++) + if (lease.options[i].len > 0) + free(lease.options[i].data); + + break; + case IMSG_SCRIPT_GO: + if (hdr.len != sizeof(hdr)) + error("corrupted message received"); + + ret = priv_script_go(); + + hdr.code = IMSG_SCRIPT_GO_RET; + hdr.len = sizeof(struct imsg_hdr) + sizeof(int); + if ((buf = buf_open(hdr.len)) == NULL) + error("buf_open: %m"); + if (buf_add(buf, &hdr, sizeof(hdr))) + error("buf_add: %m"); + if (buf_add(buf, &ret, sizeof(ret))) + error("buf_add: %m"); + if (buf_close(fd, buf) == -1) + error("buf_close: %m"); + break; + default: + error("received unknown message, code %d", hdr.code); + } +}
\ No newline at end of file |