]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/dhclient/privsep.c
Remove spurious newline
[FreeBSD/FreeBSD.git] / sbin / dhclient / privsep.c
1 /*      $OpenBSD: privsep.c,v 1.7 2004/05/10 18:34:42 deraadt Exp $ */
2
3 /*
4  * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
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 __FBSDID("$FreeBSD$");
21
22 #include "dhcpd.h"
23 #include "privsep.h"
24
25 struct buf *
26 buf_open(size_t len)
27 {
28         struct buf      *buf;
29
30         if ((buf = calloc(1, sizeof(struct buf))) == NULL)
31                 return (NULL);
32         if ((buf->buf = malloc(len)) == NULL) {
33                 free(buf);
34                 return (NULL);
35         }
36         buf->size = len;
37
38         return (buf);
39 }
40
41 int
42 buf_add(struct buf *buf, const void *data, size_t len)
43 {
44         if (buf->wpos + len > buf->size)
45                 return (-1);
46
47         memcpy(buf->buf + buf->wpos, data, len);
48         buf->wpos += len;
49         return (0);
50 }
51
52 int
53 buf_close(int sock, struct buf *buf)
54 {
55         ssize_t n;
56
57         do {
58                 n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos);
59                 if (n != -1)
60                         buf->rpos += n;
61                 if (n == 0) {                   /* connection closed */
62                         errno = 0;
63                         return (-1);
64                 }
65         } while (n == -1 && (errno == EAGAIN || errno == EINTR));
66
67         if (buf->rpos < buf->size)
68                 error("short write: wanted %lu got %ld bytes",
69                     (unsigned long)buf->size, (long)buf->rpos);
70
71         free(buf->buf);
72         free(buf);
73         return (n);
74 }
75
76 ssize_t
77 buf_read(int sock, void *buf, size_t nbytes)
78 {
79         ssize_t n;
80         size_t r = 0;
81         char *p = buf;
82
83         do {
84                 n = read(sock, p, nbytes);
85                 if (n == 0)
86                         error("connection closed");
87                 if (n != -1) {
88                         r += (size_t)n;
89                         p += n;
90                         nbytes -= n;
91                 }
92         } while (n == -1 && (errno == EINTR || errno == EAGAIN));
93
94         if (n == -1)
95                 error("buf_read: %m");
96
97         if (r < nbytes)
98                 error("short read: wanted %lu got %ld bytes",
99                     (unsigned long)nbytes, (long)r);
100
101         return (r);
102 }
103
104 void
105 dispatch_imsg(struct interface_info *ifix, int fd)
106 {
107         struct imsg_hdr          hdr;
108         char                    *medium, *reason, *filename,
109                                 *servername, *prefix;
110         size_t                   medium_len, reason_len, filename_len,
111                                  servername_len, optlen, prefix_len, totlen;
112         struct client_lease      lease;
113         int                      ret, i;
114         struct buf              *buf;
115         u_int16_t               mtu;
116
117         buf_read(fd, &hdr, sizeof(hdr));
118
119         switch (hdr.code) {
120         case IMSG_SCRIPT_INIT:
121                 if (hdr.len < sizeof(hdr) + sizeof(size_t))
122                         error("corrupted message received");
123                 buf_read(fd, &medium_len, sizeof(medium_len));
124                 if (hdr.len < medium_len + sizeof(size_t) + sizeof(hdr)
125                     + sizeof(size_t) || medium_len == SIZE_T_MAX)
126                         error("corrupted message received");
127                 if (medium_len > 0) {
128                         if ((medium = calloc(1, medium_len + 1)) == NULL)
129                                 error("%m");
130                         buf_read(fd, medium, medium_len);
131                 } else
132                         medium = NULL;
133
134                 buf_read(fd, &reason_len, sizeof(reason_len));
135                 if (hdr.len < medium_len + reason_len + sizeof(hdr) ||
136                     reason_len == SIZE_T_MAX)
137                         error("corrupted message received");
138                 if (reason_len > 0) {
139                         if ((reason = calloc(1, reason_len + 1)) == NULL)
140                                 error("%m");
141                         buf_read(fd, reason, reason_len);
142                 } else
143                         reason = NULL;
144
145                 priv_script_init(reason, medium);
146                 free(reason);
147                 free(medium);
148                 break;
149         case IMSG_SCRIPT_WRITE_PARAMS:
150                 bzero(&lease, sizeof lease);
151                 totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t);
152                 if (hdr.len < totlen)
153                         error("corrupted message received");
154                 buf_read(fd, &lease, sizeof(lease));
155
156                 buf_read(fd, &filename_len, sizeof(filename_len));
157                 totlen += filename_len + sizeof(size_t);
158                 if (hdr.len < totlen || filename_len == SIZE_T_MAX)
159                         error("corrupted message received");
160                 if (filename_len > 0) {
161                         if ((filename = calloc(1, filename_len + 1)) == NULL)
162                                 error("%m");
163                         buf_read(fd, filename, filename_len);
164                 } else
165                         filename = NULL;
166
167                 buf_read(fd, &servername_len, sizeof(servername_len));
168                 totlen += servername_len + sizeof(size_t);
169                 if (hdr.len < totlen || servername_len == SIZE_T_MAX)
170                         error("corrupted message received");
171                 if (servername_len > 0) {
172                         if ((servername =
173                             calloc(1, servername_len + 1)) == NULL)
174                                 error("%m");
175                         buf_read(fd, servername, servername_len);
176                 } else
177                         servername = NULL;
178
179                 buf_read(fd, &prefix_len, sizeof(prefix_len));
180                 totlen += prefix_len;
181                 if (hdr.len < totlen || prefix_len == SIZE_T_MAX)
182                         error("corrupted message received");
183                 if (prefix_len > 0) {
184                         if ((prefix = calloc(1, prefix_len + 1)) == NULL)
185                                 error("%m");
186                         buf_read(fd, prefix, prefix_len);
187                 } else
188                         prefix = NULL;
189
190                 for (i = 0; i < 256; i++) {
191                         totlen += sizeof(optlen);
192                         if (hdr.len < totlen)
193                                 error("corrupted message received");
194                         buf_read(fd, &optlen, sizeof(optlen));
195                         lease.options[i].data = NULL;
196                         lease.options[i].len = optlen;
197                         if (optlen > 0) {
198                                 totlen += optlen;
199                                 if (hdr.len < totlen || optlen == SIZE_T_MAX)
200                                         error("corrupted message received");
201                                 lease.options[i].data =
202                                     calloc(1, optlen + 1);
203                                 if (lease.options[i].data == NULL)
204                                     error("%m");
205                                 buf_read(fd, lease.options[i].data, optlen);
206                         }
207                 }
208                 lease.server_name = servername;
209                 lease.filename = filename;
210
211                 priv_script_write_params(prefix, &lease);
212
213                 free(servername);
214                 free(filename);
215                 free(prefix);
216                 for (i = 0; i < 256; i++)
217                         if (lease.options[i].len > 0)
218                                 free(lease.options[i].data);
219                 break;
220         case IMSG_SCRIPT_GO:
221                 if (hdr.len != sizeof(hdr))
222                         error("corrupted message received");
223
224                 ret = priv_script_go();
225
226                 hdr.code = IMSG_SCRIPT_GO_RET;
227                 hdr.len = sizeof(struct imsg_hdr) + sizeof(int);
228                 if ((buf = buf_open(hdr.len)) == NULL)
229                         error("buf_open: %m");
230                 if (buf_add(buf, &hdr, sizeof(hdr)))
231                         error("buf_add: %m");
232                 if (buf_add(buf, &ret, sizeof(ret)))
233                         error("buf_add: %m");
234                 if (buf_close(fd, buf) == -1)
235                         error("buf_close: %m");
236                 break;
237         case IMSG_SEND_PACKET:
238                 send_packet_priv(ifix, &hdr, fd);
239                 break;
240         case IMSG_SET_INTERFACE_MTU:
241                 if (hdr.len < sizeof(hdr) + sizeof(u_int16_t))
242                         error("corrupted message received");    
243         
244                 buf_read(fd, &mtu, sizeof(u_int16_t));
245                 interface_set_mtu_priv(ifix->name, mtu);
246                 break;
247         default:
248                 error("received unknown message, code %d", hdr.code);
249         }
250 }