Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/dhclient/privsep.c
39564 views
1
/* $OpenBSD: privsep.c,v 1.7 2004/05/10 18:34:42 deraadt Exp $ */
2
3
/*
4
* Copyright (c) 2004 Henning Brauer <[email protected]>
5
*
6
* Permission to use, copy, modify, and distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
9
*
10
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
15
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16
* OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#include <sys/cdefs.h>
20
#include "dhcpd.h"
21
#include "privsep.h"
22
23
struct buf *
24
buf_open(size_t len)
25
{
26
struct buf *buf;
27
28
if ((buf = calloc(1, sizeof(struct buf))) == NULL)
29
return (NULL);
30
if ((buf->buf = malloc(len)) == NULL) {
31
free(buf);
32
return (NULL);
33
}
34
buf->size = len;
35
36
return (buf);
37
}
38
39
int
40
buf_add(struct buf *buf, const void *data, size_t len)
41
{
42
if (buf->wpos + len > buf->size)
43
return (-1);
44
45
memcpy(buf->buf + buf->wpos, data, len);
46
buf->wpos += len;
47
return (0);
48
}
49
50
int
51
buf_close(int sock, struct buf *buf)
52
{
53
ssize_t n;
54
55
do {
56
n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos);
57
if (n != -1)
58
buf->rpos += n;
59
if (n == 0) { /* connection closed */
60
errno = 0;
61
return (-1);
62
}
63
} while (n == -1 && (errno == EAGAIN || errno == EINTR));
64
65
if (buf->rpos < buf->size)
66
error("short write: wanted %lu got %ld bytes",
67
(unsigned long)buf->size, (long)buf->rpos);
68
69
free(buf->buf);
70
free(buf);
71
return (n);
72
}
73
74
ssize_t
75
buf_read(int sock, void *buf, size_t nbytes)
76
{
77
ssize_t n;
78
size_t r = 0;
79
char *p = buf;
80
81
do {
82
n = read(sock, p, nbytes);
83
if (n == 0)
84
error("connection closed");
85
if (n != -1) {
86
r += (size_t)n;
87
p += n;
88
nbytes -= n;
89
}
90
} while (n == -1 && (errno == EINTR || errno == EAGAIN));
91
92
if (n == -1)
93
error("buf_read: %m");
94
95
if (r < nbytes)
96
error("short read: wanted %lu got %ld bytes",
97
(unsigned long)nbytes, (long)r);
98
99
return (r);
100
}
101
102
void
103
dispatch_imsg(struct interface_info *ifix, int fd)
104
{
105
struct imsg_hdr hdr;
106
char *medium, *reason, *filename,
107
*servername, *prefix;
108
size_t medium_len, reason_len, filename_len,
109
servername_len, optlen, prefix_len, totlen;
110
struct client_lease lease;
111
int ret, i;
112
struct buf *buf;
113
u_int16_t mtu;
114
115
buf_read(fd, &hdr, sizeof(hdr));
116
117
switch (hdr.code) {
118
case IMSG_SCRIPT_INIT:
119
if (hdr.len < sizeof(hdr) + sizeof(size_t))
120
error("corrupted message received");
121
buf_read(fd, &medium_len, sizeof(medium_len));
122
if (hdr.len < medium_len + sizeof(size_t) + sizeof(hdr)
123
+ sizeof(size_t) || medium_len == SIZE_T_MAX)
124
error("corrupted message received");
125
if (medium_len > 0) {
126
if ((medium = calloc(1, medium_len + 1)) == NULL)
127
error("%m");
128
buf_read(fd, medium, medium_len);
129
} else
130
medium = NULL;
131
132
buf_read(fd, &reason_len, sizeof(reason_len));
133
if (hdr.len < medium_len + reason_len + sizeof(hdr) ||
134
reason_len == SIZE_T_MAX)
135
error("corrupted message received");
136
if (reason_len > 0) {
137
if ((reason = calloc(1, reason_len + 1)) == NULL)
138
error("%m");
139
buf_read(fd, reason, reason_len);
140
} else
141
reason = NULL;
142
143
priv_script_init(reason, medium);
144
free(reason);
145
free(medium);
146
break;
147
case IMSG_SCRIPT_WRITE_PARAMS:
148
bzero(&lease, sizeof lease);
149
totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t);
150
if (hdr.len < totlen)
151
error("corrupted message received");
152
buf_read(fd, &lease, sizeof(lease));
153
154
buf_read(fd, &filename_len, sizeof(filename_len));
155
totlen += filename_len + sizeof(size_t);
156
if (hdr.len < totlen || filename_len == SIZE_T_MAX)
157
error("corrupted message received");
158
if (filename_len > 0) {
159
if ((filename = calloc(1, filename_len + 1)) == NULL)
160
error("%m");
161
buf_read(fd, filename, filename_len);
162
} else
163
filename = NULL;
164
165
buf_read(fd, &servername_len, sizeof(servername_len));
166
totlen += servername_len + sizeof(size_t);
167
if (hdr.len < totlen || servername_len == SIZE_T_MAX)
168
error("corrupted message received");
169
if (servername_len > 0) {
170
if ((servername =
171
calloc(1, servername_len + 1)) == NULL)
172
error("%m");
173
buf_read(fd, servername, servername_len);
174
} else
175
servername = NULL;
176
177
buf_read(fd, &prefix_len, sizeof(prefix_len));
178
totlen += prefix_len;
179
if (hdr.len < totlen || prefix_len == SIZE_T_MAX)
180
error("corrupted message received");
181
if (prefix_len > 0) {
182
if ((prefix = calloc(1, prefix_len + 1)) == NULL)
183
error("%m");
184
buf_read(fd, prefix, prefix_len);
185
} else
186
prefix = NULL;
187
188
for (i = 0; i < 256; i++) {
189
totlen += sizeof(optlen);
190
if (hdr.len < totlen)
191
error("corrupted message received");
192
buf_read(fd, &optlen, sizeof(optlen));
193
lease.options[i].data = NULL;
194
lease.options[i].len = optlen;
195
if (optlen > 0) {
196
totlen += optlen;
197
if (hdr.len < totlen || optlen == SIZE_T_MAX)
198
error("corrupted message received");
199
lease.options[i].data =
200
calloc(1, optlen + 1);
201
if (lease.options[i].data == NULL)
202
error("%m");
203
buf_read(fd, lease.options[i].data, optlen);
204
}
205
}
206
lease.server_name = servername;
207
lease.filename = filename;
208
209
priv_script_write_params(prefix, &lease);
210
211
free(servername);
212
free(filename);
213
free(prefix);
214
for (i = 0; i < 256; i++)
215
if (lease.options[i].len > 0)
216
free(lease.options[i].data);
217
break;
218
case IMSG_SCRIPT_GO:
219
if (hdr.len != sizeof(hdr))
220
error("corrupted message received");
221
222
ret = priv_script_go();
223
224
hdr.code = IMSG_SCRIPT_GO_RET;
225
hdr.len = sizeof(struct imsg_hdr) + sizeof(int);
226
if ((buf = buf_open(hdr.len)) == NULL)
227
error("buf_open: %m");
228
if (buf_add(buf, &hdr, sizeof(hdr)))
229
error("buf_add: %m");
230
if (buf_add(buf, &ret, sizeof(ret)))
231
error("buf_add: %m");
232
if (buf_close(fd, buf) == -1)
233
error("buf_close: %m");
234
break;
235
case IMSG_SEND_PACKET:
236
send_packet_priv(ifix, &hdr, fd);
237
break;
238
case IMSG_SET_INTERFACE_MTU:
239
if (hdr.len < sizeof(hdr) + sizeof(u_int16_t))
240
error("corrupted message received");
241
242
buf_read(fd, &mtu, sizeof(u_int16_t));
243
interface_set_mtu_priv(ifix->name, mtu);
244
break;
245
default:
246
error("received unknown message, code %d", hdr.code);
247
}
248
}
249
250