aboutsummaryrefslogtreecommitdiff
path: root/src/vpn/gnunet-helper-vpn.c
diff options
context:
space:
mode:
authorPhilipp Tölke <toelke@in.tum.de>2011-01-19 08:27:28 +0000
committerPhilipp Tölke <toelke@in.tum.de>2011-01-19 08:27:28 +0000
commit141a5f317de0b3a2998be41464a9b3c586fa898b (patch)
tree4ef4b2ecdb386fa087cc79c858449cd897a3dd68 /src/vpn/gnunet-helper-vpn.c
parent2df8d5de12487746f38f2887fa9bf13122afc4c6 (diff)
downloadgnunet-141a5f317de0b3a2998be41464a9b3c586fa898b.tar.gz
gnunet-141a5f317de0b3a2998be41464a9b3c586fa898b.zip
cleaned up the suid-program
Diffstat (limited to 'src/vpn/gnunet-helper-vpn.c')
-rw-r--r--src/vpn/gnunet-helper-vpn.c553
1 files changed, 313 insertions, 240 deletions
diff --git a/src/vpn/gnunet-helper-vpn.c b/src/vpn/gnunet-helper-vpn.c
index 1d21a431f..c2ebe6c7b 100644
--- a/src/vpn/gnunet-helper-vpn.c
+++ b/src/vpn/gnunet-helper-vpn.c
@@ -20,7 +20,9 @@
20 20
21/** 21/**
22 * @file vpn/gnunet-daemon-vpn.c 22 * @file vpn/gnunet-daemon-vpn.c
23 * @brief 23 * @brief the helper for various vpn-daemons. Opens a virtual network-interface,
24 * sends data received on the if to stdout, sends data received on stdin to the
25 * interface
24 * @author Philipp Tölke 26 * @author Philipp Tölke
25 */ 27 */
26#include <platform.h> 28#include <platform.h>
@@ -31,280 +33,351 @@
31#include "gnunet-vpn-helper-p.h" 33#include "gnunet-vpn-helper-p.h"
32 34
33#ifndef _LINUX_IN6_H 35#ifndef _LINUX_IN6_H
34// This is in linux/include/net/ipv6.h.
35 36
36#define MAX_SIZE (65535 - sizeof(struct GNUNET_MessageHeader)) 37#define MAX_SIZE (65535 - sizeof(struct GNUNET_MessageHeader))
37 38
38struct in6_ifreq { 39// This is in linux/include/net/ipv6.h.
39 struct in6_addr ifr6_addr; 40struct in6_ifreq
40 uint32_t ifr6_prefixlen; 41{
41 unsigned int ifr6_ifindex; 42 struct in6_addr ifr6_addr;
43 uint32_t ifr6_prefixlen;
44 unsigned int ifr6_ifindex;
42}; 45};
43 46
44#endif 47#endif
45 48
46int running = 1; 49static int running = 1;
47 50
48void term(int sig) { 51static void
49 fprintf(stderr, "Got SIGTERM...\n"); 52term (int sig)
50 if (sig == SIGTERM) 53{
51 running = 0; 54 fprintf (stderr, "Got SIGTERM...\n");
55 if (sig == SIGTERM)
56 running = 0;
52} 57}
53 58
54static void set_address6(char* dev, char* address, unsigned long prefix_len) { /* {{{ */ 59/**
55 int fd = socket(AF_INET6, SOCK_DGRAM, 0); 60 * @brief Sets the IPv6-Address given in address on the interface dev
56 61 *
57 if (fd < 0) 62 * @param dev the interface to configure
58 { 63 * @param address the IPv6-Address
59 fprintf(stderr, "error creating socket: %m\n"); 64 * @param prefix_len the length of the network-prefix
60 exit(1); 65 */
61 } 66static void
62 67set_address6 (char *dev, char *address, unsigned long prefix_len)
63 struct ifreq ifr; 68{ /* {{{ */
64 struct in6_ifreq ifr6; 69 int fd = socket (AF_INET6, SOCK_DGRAM, 0);
65
66 struct sockaddr_in6 sa6;
67 memset(&sa6, 0, sizeof(struct sockaddr_in6));
68
69 sa6.sin6_family = AF_INET6;
70
71 int r = inet_pton(AF_INET6, address, sa6.sin6_addr.s6_addr);
72 if (r < 0)
73 {
74 fprintf(stderr, "error at inet_pton: %m\n");
75 exit(1);
76 }
77
78 memcpy((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr, sizeof(struct in6_addr));
79
80 strncpy(ifr.ifr_name, dev, IFNAMSIZ);
81
82 if (ioctl(fd, SIOGIFINDEX, &ifr) < 0) {
83 perror("SIOGIFINDEX");
84 }
85 70
86 ifr6.ifr6_ifindex = ifr.ifr_ifindex; 71 if (fd < 0)
87 ifr6.ifr6_prefixlen = prefix_len; 72 {
73 fprintf (stderr, "error creating socket: %m\n");
74 exit (1);
75 }
88 76
89 if (ioctl(fd, SIOCSIFADDR, &ifr6) < 0) { 77 struct ifreq ifr;
90 perror("SIOCSIFADDR"); 78 struct in6_ifreq ifr6;
91 }
92 79
93 (void)ioctl(fd, SIOCGIFFLAGS, &ifr); 80 struct sockaddr_in6 sa6;
94 ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 81 memset (&sa6, 0, sizeof (struct sockaddr_in6));
95 (void)ioctl(fd, SIOCSIFFLAGS, &ifr);
96 close(fd);
97} /* }}} */
98
99static void set_address4(char* dev, char* address, char* mask) { /* {{{ */
100 int fd=0;
101 struct sockaddr_in* addr;
102 struct ifreq ifr;
103
104 memset(&ifr, 0, sizeof(struct ifreq));
105 addr = (struct sockaddr_in *)&(ifr.ifr_addr);
106 memset(addr, 0, sizeof(struct sockaddr_in));
107 addr->sin_family = AF_INET;
108 addr->sin_addr.s_addr = inet_addr(address);
109
110 int r = inet_pton(AF_INET, address, &addr->sin_addr.s_addr);
111 if (r < 0)
112 {
113 fprintf(stderr, "error at inet_pton: %m\n");
114 exit(1);
115 }
116
117 fd = socket(PF_INET, SOCK_DGRAM, 0);
118 if(fd < 0) {
119 perror("socket()");
120 return;
121 }
122 82
123 strncpy(ifr.ifr_name, dev, IFNAMSIZ); 83 sa6.sin6_family = AF_INET6;
124 84
125 if(ioctl(fd, SIOCSIFADDR, &ifr) != 0 ) { 85 int r = inet_pton (AF_INET6, address, sa6.sin6_addr.s6_addr);
126 perror("SIOCSIFADDR"); 86 if (r < 0)
127 close(fd); 87 {
128 return; 88 fprintf (stderr, "error at inet_pton: %m\n");
129 } 89 exit (1);
130 90 }
131 addr = (struct sockaddr_in*)&(ifr.ifr_netmask);
132 r = inet_pton(AF_INET, mask, &addr->sin_addr.s_addr);
133 if (r < 0)
134 {
135 fprintf(stderr, "error at inet_pton: %m\n");
136 exit(1);
137 }
138
139 if(ioctl(fd, SIOCSIFNETMASK, &ifr) != 0 ) {
140 perror("SIOCSIFNETMASK");
141 close(fd);
142 return;
143 }
144 91
145 (void)ioctl(fd, SIOCGIFFLAGS, &ifr); 92 memcpy ((char *) &ifr6.ifr6_addr, (char *) &sa6.sin6_addr,
146 ifr.ifr_flags |= IFF_UP | IFF_RUNNING; 93 sizeof (struct in6_addr));
147 (void)ioctl(fd, SIOCSIFFLAGS, &ifr);
148 close(fd);
149} /* }}} */
150 94
151void setnonblocking(int fd) {/*{{{*/ 95 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
152 int opts;
153 96
154 opts = fcntl(fd,F_GETFL); 97 if (ioctl (fd, SIOGIFINDEX, &ifr) < 0)
155 if (opts < 0) { 98 {
156 perror("fcntl(F_GETFL)"); 99 perror ("SIOGIFINDEX");
157 } 100 }
158 opts = (opts | O_NONBLOCK);
159 if (fcntl(fd,F_SETFL,opts) < 0) {
160 perror("fcntl(F_SETFL)");
161 }
162 return;
163}/*}}}*/
164 101
165int main(int argc, char** argv) { 102 ifr6.ifr6_ifindex = ifr.ifr_ifindex;
166 unsigned char buf[MAX_SIZE]; 103 ifr6.ifr6_prefixlen = prefix_len;
167 104
168 char dev[IFNAMSIZ]; 105 if (ioctl (fd, SIOCSIFADDR, &ifr6) < 0)
169 memset(dev, 0, IFNAMSIZ); 106 {
107 perror ("SIOCSIFADDR");
108 }
170 109
171 signal(SIGTERM, &term); 110 (void) ioctl (fd, SIOCGIFFLAGS, &ifr);
111 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
112 (void) ioctl (fd, SIOCSIFFLAGS, &ifr);
113 close (fd);
114} /* }}} */
172 115
173 int fd_tun = init_tun(dev); 116static void
117/**
118 * @brief Sets the IPv4-Address given in address on the interface dev
119 *
120 * @param dev the interface to configure
121 * @param address the IPv4-Address
122 * @param mask the netmask
123 */
124set_address4 (char *dev, char *address, char *mask)
125{ /* {{{ */
126 int fd = 0;
127 struct sockaddr_in *addr;
128 struct ifreq ifr;
129
130 memset (&ifr, 0, sizeof (struct ifreq));
131 addr = (struct sockaddr_in *) &(ifr.ifr_addr);
132 memset (addr, 0, sizeof (struct sockaddr_in));
133 addr->sin_family = AF_INET;
134 addr->sin_addr.s_addr = inet_addr (address);
135
136 int r = inet_pton (AF_INET, address, &addr->sin_addr.s_addr);
137 if (r < 0)
138 {
139 fprintf (stderr, "error at inet_pton: %m\n");
140 exit (1);
141 }
142
143 fd = socket (PF_INET, SOCK_DGRAM, 0);
144 if (fd < 0)
145 {
146 perror ("socket()");
147 return;
148 }
149
150 strncpy (ifr.ifr_name, dev, IFNAMSIZ);
151
152 if (ioctl (fd, SIOCSIFADDR, &ifr) != 0)
153 {
154 perror ("SIOCSIFADDR");
155 close (fd);
156 return;
157 }
158
159 addr = (struct sockaddr_in *) &(ifr.ifr_netmask);
160 r = inet_pton (AF_INET, mask, &addr->sin_addr.s_addr);
161 if (r < 0)
162 {
163 fprintf (stderr, "error at inet_pton: %m\n");
164 exit (1);
165 }
166
167 if (ioctl (fd, SIOCSIFNETMASK, &ifr) != 0)
168 {
169 perror ("SIOCSIFNETMASK");
170 close (fd);
171 return;
172 }
173
174 (void) ioctl (fd, SIOCGIFFLAGS, &ifr);
175 ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
176 (void) ioctl (fd, SIOCSIFFLAGS, &ifr);
177 close (fd);
178} /* }}} */
174 179
175 if (fd_tun < 0) { 180/**
176 fprintf(stderr, "Could not initialize tun-interface: %s\n", strerror(errno)); 181 * @brief sets the socket to nonblocking
177 exit(1); 182 *
178 } 183 * @param fd the socket
184 */
185static void
186setnonblocking (int fd)
187{ /*{{{ */
188 int opts;
189
190 opts = fcntl (fd, F_GETFL);
191 if (opts < 0)
192 {
193 perror ("fcntl(F_GETFL)");
194 }
195 opts = (opts | O_NONBLOCK);
196 if (fcntl (fd, F_SETFL, opts) < 0)
197 {
198 perror ("fcntl(F_SETFL)");
199 }
200 return;
201} /*}}} */
202
203int
204main (int argc, char **argv)
205{
206 unsigned char buf[MAX_SIZE];
207
208 char dev[IFNAMSIZ];
209 memset (dev, 0, IFNAMSIZ);
210
211 signal (SIGTERM, &term);
212
213 int fd_tun = init_tun (dev);
214
215 if (fd_tun < 0)
216 {
217 fprintf (stderr, "Could not initialize tun-interface: %s\n",
218 strerror (errno));
219 exit (1);
220 }
221
222 {
223 // TODO: get this out of argv
224 char address[] = "1234::1";
225 unsigned long prefix_len = 16;
226
227 set_address6 (dev, address, prefix_len);
228 }
229
230 {
231 char address[] = "10.10.10.1";
232 char mask[] = "255.255.255.252";
233
234 set_address4 (dev, address, mask);
235 }
236
237 uid_t uid = getuid ();
238 if (setresuid (uid, uid, uid) != 0)
239 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
240
241 setnonblocking (0);
242 setnonblocking (1);
243 setnonblocking (fd_tun);
244
245 fd_set fds_w;
246 fd_set fds_r;
247
248 int rea = 1;
249 int wri = 1;
250
251 int write_fd_possible = 0;
252 int write_stdout_possible = 0;
253outer:
254 while ((rea == 1 || wri == 1) && running == 1)
255 {
256 FD_ZERO (&fds_w);
257 FD_ZERO (&fds_r);
179 258
259 if (rea)
180 { 260 {
181 // TODO: get this out of argv 261 FD_SET (fd_tun, &fds_r);
182 char address[] = "1234::1"; 262 if (!write_stdout_possible)
183 unsigned long prefix_len = 16; 263 FD_SET (1, &fds_w);
184
185 set_address6(dev, address, prefix_len);
186 } 264 }
187 265
266 if (wri)
188 { 267 {
189 char address[] = "10.10.10.1"; 268 FD_SET (0, &fds_r);
190 char mask[] = "255.255.255.252"; 269 if (!write_fd_possible)
191 270 FD_SET (fd_tun, &fds_w);
192 set_address4(dev, address, mask);
193 } 271 }
194 272
195 uid_t uid = getuid (); 273 int r = select (fd_tun + 1, &fds_r, &fds_w, (fd_set *) 0, 0);
196 if (setresuid (uid, uid, uid) != 0 )
197 fprintf (stderr, "Failed to setresuid: %s\n", strerror(errno));
198
199 setnonblocking(0);
200 setnonblocking(1);
201 setnonblocking(fd_tun);
202 274
203 fd_set fds_w; 275 if (r > 0)
204 fd_set fds_r; 276 {
205 277 if (FD_ISSET (fd_tun, &fds_w))
206 int rea = 1; 278 write_fd_possible = 1;
207 int wri = 1; 279 if (FD_ISSET (1, &fds_w))
208 280 write_stdout_possible = 1;
209 int write_fd_possible = 0; 281
210 int write_stdout_possible = 0; 282 if (FD_ISSET (0, &fds_r) && write_fd_possible)
211outer: 283 {
212 while((rea == 1 || wri == 1) && running == 1) { 284 write_fd_possible = 0;
213 FD_ZERO(&fds_w); 285 struct suid_packet *pkt = (struct suid_packet *) buf;
214 FD_ZERO(&fds_r); 286 r = read (0, buf, sizeof (struct GNUNET_MessageHeader));
215 287 if (r <= 0)
216 if (rea) { 288 {
217 FD_SET(fd_tun, &fds_r); 289 fprintf (stderr, "read-error: %s\n", strerror (errno));
218 if (!write_stdout_possible) 290 shutdown (fd_tun, SHUT_WR);
219 FD_SET(1, &fds_w); 291 shutdown (0, SHUT_RD);
292 wri = 0;
293 goto outer;
220 } 294 }
221 295 if (pkt->hdr.type != ntohs (GNUNET_MESSAGE_TYPE_VPN_HELPER))
222 if (wri) { 296 abort ();
223 FD_SET(0, &fds_r); 297 while (r < ntohs (pkt->hdr.size))
224 if (!write_fd_possible) 298 {
225 FD_SET(fd_tun, &fds_w); 299 int t = read (0, buf + r, ntohs (pkt->hdr.size) - r);
300 if (r < 0)
301 {
302 fprintf (stderr, "read-error: %s\n", strerror (errno));
303 shutdown (fd_tun, SHUT_WR);
304 shutdown (0, SHUT_RD);
305 wri = 0;
306 goto outer;
307 }
308 r += t;
226 } 309 }
227 310 r = 0;
228 int r = select(fd_tun+1, &fds_r, &fds_w, (fd_set*)0, 0); 311 while (r <
229 312 ntohs (pkt->hdr.size) -
230 if(r > 0) { 313 sizeof (struct GNUNET_MessageHeader))
231 if (FD_ISSET(fd_tun, &fds_w)) write_fd_possible = 1; 314 {
232 if (FD_ISSET(1, &fds_w)) write_stdout_possible = 1; 315 int t = write (fd_tun, pkt->data,
233 316 ntohs (pkt->hdr.size) -
234 if (FD_ISSET(0, &fds_r) && write_fd_possible) { 317 sizeof (struct GNUNET_MessageHeader) - r);
235 write_fd_possible = 0; 318 if (t < 0)
236 struct suid_packet *pkt = (struct suid_packet*) buf; 319 {
237 r = read(0, buf, sizeof(struct GNUNET_MessageHeader)); 320 fprintf (stderr, "write-error 3: %s\n",
238 if (r <= 0) { 321 strerror (errno));
239 fprintf(stderr, "read-error: %s\n", strerror (errno)); 322 shutdown (fd_tun, SHUT_WR);
240 shutdown(fd_tun, SHUT_WR); 323 shutdown (0, SHUT_RD);
241 shutdown(0, SHUT_RD); 324 wri = 0;
242 wri=0; 325 goto outer;
243 goto outer; 326 }
244 } 327 r += t;
245 if(pkt->hdr.type != ntohs(GNUNET_MESSAGE_TYPE_VPN_HELPER)) abort(); 328 }
246 while (r < ntohs(pkt->hdr.size)) { 329 }
247 int t = read(0, buf + r, ntohs(pkt->hdr.size) - r); 330 else if (write_stdout_possible && FD_ISSET (fd_tun, &fds_r))
248 if (r < 0) { 331 {
249 fprintf(stderr, "read-error: %s\n", strerror (errno)); 332 write_stdout_possible = 0;
250 shutdown(fd_tun, SHUT_WR); 333 r = read (fd_tun, buf, MAX_SIZE);
251 shutdown(0, SHUT_RD); 334 if (r <= 0)
252 wri=0; 335 {
253 goto outer; 336 fprintf (stderr, "read-error: %s\n", strerror (errno));
254 } 337 shutdown (fd_tun, SHUT_RD);
255 r += t; 338 shutdown (1, SHUT_WR);
256 } 339 rea = 0;
257 r = 0; 340 goto outer;
258 while (r < ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader)) { 341 }
259 int t = write(fd_tun, pkt->data, ntohs(pkt->hdr.size) - sizeof(struct GNUNET_MessageHeader) - r); 342 struct GNUNET_MessageHeader hdr = {.size =
260 if (t < 0) { 343 htons (r + sizeof (struct GNUNET_MessageHeader)),.type =
261 fprintf(stderr, "write-error 3: %s\n", strerror (errno)); 344 htons (GNUNET_MESSAGE_TYPE_VPN_HELPER)
262 shutdown(fd_tun, SHUT_WR); 345 };
263 shutdown(0, SHUT_RD); 346 r = 0;
264 wri = 0; 347 while (r < sizeof (struct GNUNET_MessageHeader))
265 goto outer; 348 {
266 } 349 int t =
267 r += t; 350 write (1, &hdr, sizeof (struct GNUNET_MessageHeader) - r);
268 } 351 if (t < 0)
269 } else if (write_stdout_possible && FD_ISSET(fd_tun, &fds_r)) { 352 {
270 write_stdout_possible = 0; 353 fprintf (stderr, "write-error 2: %s\n",
271 r = read(fd_tun, buf, MAX_SIZE); 354 strerror (errno));
272 if (r <= 0) { 355 shutdown (fd_tun, SHUT_RD);
273 fprintf(stderr, "read-error: %s\n", strerror (errno)); 356 shutdown (1, SHUT_WR);
274 shutdown(fd_tun, SHUT_RD); 357 rea = 0;
275 shutdown(1, SHUT_WR); 358 goto outer;
276 rea = 0; 359 }
277 goto outer; 360 r += t;
278 } 361 }
279 struct GNUNET_MessageHeader hdr = { .size = htons(r + sizeof(struct GNUNET_MessageHeader)), .type = htons(GNUNET_MESSAGE_TYPE_VPN_HELPER) }; 362 while (r < ntohs (hdr.size))
280 r = 0; 363 {
281 while(r < sizeof(struct GNUNET_MessageHeader)) { 364 int t = write (1, buf, ntohs (hdr.size) - r);
282 int t = write(1, &hdr, sizeof(struct GNUNET_MessageHeader) - r); 365 if (t < 0)
283 if (t < 0) { 366 {
284 fprintf(stderr, "write-error 2: %s\n", strerror (errno)); 367 fprintf (stderr, "write-error 1: %s, written %d/%d\n",
285 shutdown(fd_tun, SHUT_RD); 368 strerror (errno), r, ntohs (hdr.size));
286 shutdown(1, SHUT_WR); 369 shutdown (fd_tun, SHUT_RD);
287 rea = 0; 370 shutdown (1, SHUT_WR);
288 goto outer; 371 rea = 0;
289 } 372 goto outer;
290 r += t; 373 }
291 } 374 r += t;
292 while(r < ntohs(hdr.size)) {
293 int t = write(1, buf, ntohs(hdr.size) - r);
294 if (t < 0) {
295 fprintf(stderr, "write-error 1: %s, written %d/%d\n", strerror(errno), r, ntohs(hdr.size));
296 shutdown(fd_tun, SHUT_RD);
297 shutdown(1, SHUT_WR);
298 rea = 0;
299 goto outer;
300 }
301 r += t;
302 }
303 }
304 } 375 }
376 }
305 } 377 }
378 }
306 379
307 close(fd_tun); 380 close (fd_tun);
308 381
309 return 0; 382 return 0;
310} 383}