Merge branch 'master' of ssh://crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / sbin / dhclient / privsep.c
blob646bdd76b75bade52f6e090434c4849bca982d44
1 /* $OpenBSD: privsep.c,v 1.14 2007/02/15 15:22:27 stevesk Exp $ */
2 /* $DragonFly: src/sbin/dhclient/privsep.c,v 1.1 2008/08/30 16:07:58 hasso Exp $ */
4 /*
5 * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
16 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17 * OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
20 #include "dhcpd.h"
21 #include "privsep.h"
23 struct buf *
24 buf_open(size_t len)
26 struct buf *buf;
28 if ((buf = calloc(1, sizeof(struct buf))) == NULL)
29 error("buf_open: %m");
30 if ((buf->buf = malloc(len)) == NULL) {
31 free(buf);
32 error("buf_open: %m");
34 buf->size = len;
36 return (buf);
39 void
40 buf_add(struct buf *buf, void *data, size_t len)
42 if (len == 0)
43 return;
45 if (buf->wpos + len > buf->size)
46 error("buf_add: %m");
48 memcpy(buf->buf + buf->wpos, data, len);
49 buf->wpos += len;
52 void
53 buf_close(int sock, struct buf *buf)
55 ssize_t n;
57 do {
58 n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos);
59 if (n == 0) /* connection closed */
60 error("buf_close (connection closed)");
61 if (n != -1 && n < buf->size - buf->rpos)
62 error("buf_close (short write): %m");
64 } while (n == -1 && (errno == EAGAIN || errno == EINTR));
66 if (n == -1)
67 error("buf_close: %m");
69 free(buf->buf);
70 free(buf);
73 void
74 buf_read(int sock, void *buf, size_t nbytes)
76 ssize_t n;
78 do {
79 n = read(sock, buf, nbytes);
80 if (n == 0) { /* connection closed */
81 debug("buf_read (connection closed)");
82 exit(1);
84 if (n != -1 && n < nbytes)
85 error("buf_read (short read): %m");
86 } while (n == -1 && (errno == EINTR || errno == EAGAIN));
88 if (n == -1)
89 error("buf_read: %m");
92 void
93 dispatch_imsg(int fd)
95 struct imsg_hdr hdr;
96 char *medium, *reason, *filename,
97 *servername, *prefix;
98 size_t medium_len, reason_len, filename_len,
99 servername_len, prefix_len, totlen;
100 struct client_lease lease;
101 int ret, i, optlen;
102 struct buf *buf;
104 buf_read(fd, &hdr, sizeof(hdr));
106 switch (hdr.code) {
107 case IMSG_SCRIPT_INIT:
108 if (hdr.len < sizeof(hdr) + sizeof(size_t))
109 error("corrupted message received");
110 buf_read(fd, &medium_len, sizeof(medium_len));
111 if (hdr.len < medium_len + sizeof(size_t) + sizeof(hdr)
112 + sizeof(size_t) || medium_len == SIZE_T_MAX)
113 error("corrupted message received");
114 if (medium_len > 0) {
115 if ((medium = calloc(1, medium_len + 1)) == NULL)
116 error("%m");
117 buf_read(fd, medium, medium_len);
118 } else
119 medium = NULL;
121 buf_read(fd, &reason_len, sizeof(reason_len));
122 if (hdr.len < medium_len + reason_len + sizeof(hdr) ||
123 reason_len == SIZE_T_MAX)
124 error("corrupted message received");
125 if (reason_len > 0) {
126 if ((reason = calloc(1, reason_len + 1)) == NULL)
127 error("%m");
128 buf_read(fd, reason, reason_len);
129 } else
130 reason = NULL;
132 priv_script_init(reason, medium);
133 free(reason);
134 free(medium);
135 break;
136 case IMSG_SCRIPT_WRITE_PARAMS:
137 bzero(&lease, sizeof lease);
138 totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t);
139 if (hdr.len < totlen)
140 error("corrupted message received");
141 buf_read(fd, &lease, sizeof(lease));
143 buf_read(fd, &filename_len, sizeof(filename_len));
144 totlen += filename_len + sizeof(size_t);
145 if (hdr.len < totlen || filename_len == SIZE_T_MAX)
146 error("corrupted message received");
147 if (filename_len > 0) {
148 if ((filename = calloc(1, filename_len + 1)) == NULL)
149 error("%m");
150 buf_read(fd, filename, filename_len);
151 } else
152 filename = NULL;
154 buf_read(fd, &servername_len, sizeof(servername_len));
155 totlen += servername_len + sizeof(size_t);
156 if (hdr.len < totlen || servername_len == SIZE_T_MAX)
157 error("corrupted message received");
158 if (servername_len > 0) {
159 if ((servername =
160 calloc(1, servername_len + 1)) == NULL)
161 error("%m");
162 buf_read(fd, servername, servername_len);
163 } else
164 servername = NULL;
166 buf_read(fd, &prefix_len, sizeof(prefix_len));
167 totlen += prefix_len;
168 if (hdr.len < totlen || prefix_len == SIZE_T_MAX)
169 error("corrupted message received");
170 if (prefix_len > 0) {
171 if ((prefix = calloc(1, prefix_len + 1)) == NULL)
172 error("%m");
173 buf_read(fd, prefix, prefix_len);
174 } else
175 prefix = NULL;
177 for (i = 0; i < 256; i++) {
178 totlen += sizeof(optlen);
179 if (hdr.len < totlen)
180 error("corrupted message received");
181 buf_read(fd, &optlen, sizeof(optlen));
182 lease.options[i].data = NULL;
183 lease.options[i].len = optlen;
184 if (optlen > 0) {
185 totlen += optlen;
186 if (hdr.len < totlen || optlen == SIZE_T_MAX)
187 error("corrupted message received");
188 lease.options[i].data =
189 calloc(1, optlen + 1);
190 if (lease.options[i].data == NULL)
191 error("%m");
192 buf_read(fd, lease.options[i].data, optlen);
195 lease.server_name = servername;
196 lease.filename = filename;
198 priv_script_write_params(prefix, &lease);
200 free(servername);
201 free(filename);
202 free(prefix);
203 for (i = 0; i < 256; i++)
204 if (lease.options[i].len > 0)
205 free(lease.options[i].data);
206 break;
207 case IMSG_SCRIPT_GO:
208 if (hdr.len != sizeof(hdr))
209 error("corrupted message received");
211 ret = priv_script_go();
213 hdr.code = IMSG_SCRIPT_GO_RET;
214 hdr.len = sizeof(struct imsg_hdr) + sizeof(int);
215 if ((buf = buf_open(hdr.len)) == NULL)
216 error("buf_open: %m");
217 buf_add(buf, &hdr, sizeof(hdr));
218 buf_add(buf, &ret, sizeof(ret));
219 buf_close(fd, buf);
220 break;
221 default:
222 error("received unknown message, code %d", hdr.code);