diff options
author | Christian Grothoff <christian@grothoff.org> | 2013-10-26 12:36:51 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2013-10-26 12:36:51 +0000 |
commit | aeb922926c639ffdd992f96cd125e47bb0e2c301 (patch) | |
tree | 85097e40305035ad337f0c0e8dc0f95343dbed3a | |
parent | 7679eb4a51b8d0e9e4671dae00ca83c9f1b22de7 (diff) | |
download | gnunet-aeb922926c639ffdd992f96cd125e47bb0e2c301.tar.gz gnunet-aeb922926c639ffdd992f96cd125e47bb0e2c301.zip |
-moving code to parse IPv4/IPv6 subnet specifications to strings and making it part of the public API
-rw-r--r-- | src/gns/Makefile.am | 6 | ||||
-rw-r--r-- | src/gns/gnunet-gns-proxy.c | 34 | ||||
-rw-r--r-- | src/include/gnunet_strings_lib.h | 68 | ||||
-rw-r--r-- | src/util/service.c | 325 | ||||
-rw-r--r-- | src/util/strings.c | 281 |
5 files changed, 364 insertions, 350 deletions
diff --git a/src/gns/Makefile.am b/src/gns/Makefile.am index 75c3d0133..8e701ad96 100644 --- a/src/gns/Makefile.am +++ b/src/gns/Makefile.am | |||
@@ -50,7 +50,7 @@ lib_LTLIBRARIES = \ | |||
50 | if HAVE_MHD | 50 | if HAVE_MHD |
51 | if HAVE_GNUTLS | 51 | if HAVE_GNUTLS |
52 | if HAVE_LIBGNURL | 52 | if HAVE_LIBGNURL |
53 | # DO_PROXY=gnunet-gns-proxy | 53 | DO_PROXY=gnunet-gns-proxy |
54 | endif | 54 | endif |
55 | endif | 55 | endif |
56 | endif | 56 | endif |
@@ -58,8 +58,8 @@ endif | |||
58 | libexec_PROGRAMS = \ | 58 | libexec_PROGRAMS = \ |
59 | gnunet-service-gns \ | 59 | gnunet-service-gns \ |
60 | $(DO_W32_HELPER) \ | 60 | $(DO_W32_HELPER) \ |
61 | gnunet-dns2gns | 61 | gnunet-dns2gns \ |
62 | # $(DO_PROXY) | 62 | $(DO_PROXY) |
63 | 63 | ||
64 | bin_PROGRAMS = \ | 64 | bin_PROGRAMS = \ |
65 | $(DO_W32_NSPTOOLS) \ | 65 | $(DO_W32_NSPTOOLS) \ |
diff --git a/src/gns/gnunet-gns-proxy.c b/src/gns/gnunet-gns-proxy.c index 968470bd9..4f65574dd 100644 --- a/src/gns/gnunet-gns-proxy.c +++ b/src/gns/gnunet-gns-proxy.c | |||
@@ -26,7 +26,6 @@ | |||
26 | * | 26 | * |
27 | * TODO: | 27 | * TODO: |
28 | * - double-check queueing logic | 28 | * - double-check queueing logic |
29 | * - actually check SSL certificates (#3038) | ||
30 | */ | 29 | */ |
31 | #include "platform.h" | 30 | #include "platform.h" |
32 | #include <microhttpd.h> | 31 | #include <microhttpd.h> |
@@ -877,6 +876,9 @@ check_ssl_certificate (struct Socks5Request *s5r) | |||
877 | 876 | ||
878 | /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */ | 877 | /* FIXME: add flags to gnutls to NOT read UNBOUND_ROOT_KEY_FILE here! */ |
879 | if (0 != (rc = dane_state_init (&dane_state, | 878 | if (0 != (rc = dane_state_init (&dane_state, |
879 | #ifdef DANE_F_IGNORE_DNSSEC | ||
880 | DANE_F_IGNORE_DNSSEC | | ||
881 | #endif | ||
880 | DANE_F_IGNORE_LOCAL_RESOLVER))) | 882 | DANE_F_IGNORE_LOCAL_RESOLVER))) |
881 | { | 883 | { |
882 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 884 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
@@ -957,36 +959,6 @@ check_ssl_certificate (struct Socks5Request *s5r) | |||
957 | } | 959 | } |
958 | } | 960 | } |
959 | gnutls_x509_crt_deinit (x509_cert); | 961 | gnutls_x509_crt_deinit (x509_cert); |
960 | #if 0 | ||
961 | { | ||
962 | unsigned int i; | ||
963 | |||
964 | for(i=0;i<cert_list_size;i++) | ||
965 | { | ||
966 | gnutls_x509_crt_t cert; | ||
967 | gnutls_datum_t dn; | ||
968 | |||
969 | if (GNUTLS_E_SUCCESS == gnutls_x509_crt_init (&cert)) | ||
970 | { | ||
971 | if (GNUTLS_E_SUCCESS == | ||
972 | gnutls_x509_crt_import (cert, &chainp[i], | ||
973 | GNUTLS_X509_FMT_DER)) | ||
974 | { | ||
975 | if (GNUTLS_E_SUCCESS == | ||
976 | gnutls_x509_crt_print (cert, | ||
977 | GNUTLS_CRT_PRINT_FULL, | ||
978 | &dn)) | ||
979 | { | ||
980 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
981 | "Certificate #%d: %.*s", i, dn.size, dn.data); | ||
982 | gnutls_free (dn.data); | ||
983 | } | ||
984 | } | ||
985 | gnutls_x509_crt_deinit (cert); | ||
986 | } | ||
987 | } | ||
988 | } | ||
989 | #endif | ||
990 | return GNUNET_OK; | 962 | return GNUNET_OK; |
991 | } | 963 | } |
992 | 964 | ||
diff --git a/src/include/gnunet_strings_lib.h b/src/include/gnunet_strings_lib.h index 2e6f599d1..e0a299ac3 100644 --- a/src/include/gnunet_strings_lib.h +++ b/src/include/gnunet_strings_lib.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | This file is part of GNUnet. | 2 | This file is part of GNUnet. |
3 | (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2012 Christian Grothoff (and other contributing authors) | 3 | (C) 2001-2013 Christian Grothoff (and other contributing authors) |
4 | 4 | ||
5 | GNUnet is free software; you can redistribute it and/or modify | 5 | GNUnet is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published | 6 | it under the terms of the GNU General Public License as published |
@@ -469,6 +469,72 @@ GNUNET_STRINGS_get_utf8_args (int argc, | |||
469 | char *const **u8argv); | 469 | char *const **u8argv); |
470 | 470 | ||
471 | 471 | ||
472 | /* ***************** IPv4/IPv6 parsing ****************** */ | ||
473 | |||
474 | /** | ||
475 | * @brief IPV4 network in CIDR notation. | ||
476 | */ | ||
477 | struct GNUNET_STRINGS_IPv4NetworkPolicy | ||
478 | { | ||
479 | /** | ||
480 | * IPv4 address. | ||
481 | */ | ||
482 | struct in_addr network; | ||
483 | |||
484 | /** | ||
485 | * IPv4 netmask. | ||
486 | */ | ||
487 | struct in_addr netmask; | ||
488 | }; | ||
489 | |||
490 | /** | ||
491 | |||
492 | * @brief network in CIDR notation for IPV6. | ||
493 | */ | ||
494 | struct GNUNET_STRINGS_IPv6NetworkPolicy | ||
495 | { | ||
496 | /** | ||
497 | * IPv6 address. | ||
498 | */ | ||
499 | struct in6_addr network; | ||
500 | |||
501 | /** | ||
502 | * IPv6 netmask. | ||
503 | */ | ||
504 | struct in6_addr netmask; | ||
505 | }; | ||
506 | |||
507 | |||
508 | /** | ||
509 | * Parse an IPv4 network policy. The argument specifies a list of | ||
510 | * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace, | ||
511 | * must be terminated with a semicolon). The network must be given in | ||
512 | * dotted-decimal notation. The netmask can be given in CIDR notation | ||
513 | * (/16) or in dotted-decimal (/255.255.0.0). | ||
514 | * | ||
515 | * @param routeList a string specifying the IPv4 subnets | ||
516 | * @return the converted list, terminated with all zeros; | ||
517 | * NULL if the synatx is flawed | ||
518 | */ | ||
519 | struct GNUNET_STRINGS_IPv4NetworkPolicy * | ||
520 | GNUNET_STRINGS_parse_ipv4_policy (const char *routeList); | ||
521 | |||
522 | |||
523 | /** | ||
524 | * Parse an IPv6 network policy. The argument specifies a list of | ||
525 | * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace, | ||
526 | * must be terminated with a semicolon). The network must be given in | ||
527 | * colon-hex notation. The netmask must be given in CIDR notation | ||
528 | * (/16) or can be omitted to specify a single host. | ||
529 | * | ||
530 | * @param routeListX a string specifying the policy | ||
531 | * @return the converted list, 0-terminated, NULL if the synatx is flawed | ||
532 | */ | ||
533 | struct GNUNET_STRINGS_IPv6NetworkPolicy * | ||
534 | GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX); | ||
535 | |||
536 | |||
537 | |||
472 | #if 0 /* keep Emacsens' auto-indent happy */ | 538 | #if 0 /* keep Emacsens' auto-indent happy */ |
473 | { | 539 | { |
474 | #endif | 540 | #endif |
diff --git a/src/util/service.c b/src/util/service.c index 3ba20d64a..e7d4c1c6f 100644 --- a/src/util/service.c +++ b/src/util/service.c | |||
@@ -45,40 +45,6 @@ | |||
45 | /* ******************* access control ******************** */ | 45 | /* ******************* access control ******************** */ |
46 | 46 | ||
47 | /** | 47 | /** |
48 | * @brief IPV4 network in CIDR notation. | ||
49 | */ | ||
50 | struct IPv4NetworkSet | ||
51 | { | ||
52 | /** | ||
53 | * IPv4 address. | ||
54 | */ | ||
55 | struct in_addr network; | ||
56 | |||
57 | /** | ||
58 | * IPv4 netmask. | ||
59 | */ | ||
60 | struct in_addr netmask; | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | |||
65 | * @brief network in CIDR notation for IPV6. | ||
66 | */ | ||
67 | struct IPv6NetworkSet | ||
68 | { | ||
69 | /** | ||
70 | * IPv6 address. | ||
71 | */ | ||
72 | struct in6_addr network; | ||
73 | |||
74 | /** | ||
75 | * IPv6 netmask. | ||
76 | */ | ||
77 | struct in6_addr netmask; | ||
78 | }; | ||
79 | |||
80 | |||
81 | /** | ||
82 | * Start task that may speed up our system clock artificially | 48 | * Start task that may speed up our system clock artificially |
83 | * | 49 | * |
84 | * @param cfg configuration to use | 50 | * @param cfg configuration to use |
@@ -95,277 +61,6 @@ GNUNET_SPEEDUP_stop_ (void); | |||
95 | 61 | ||
96 | 62 | ||
97 | /** | 63 | /** |
98 | * Parse a network specification. The argument specifies | ||
99 | * a list of networks. The format is | ||
100 | * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated | ||
101 | * with a semicolon). The network must be given in dotted-decimal | ||
102 | * notation. The netmask can be given in CIDR notation (/16) or | ||
103 | * in dotted-decimal (/255.255.0.0). | ||
104 | * | ||
105 | * @param routeList a string specifying the forbidden networks | ||
106 | * @return the converted list, NULL if the synatx is flawed | ||
107 | */ | ||
108 | static struct IPv4NetworkSet * | ||
109 | parse_ipv4_specification (const char *routeList) | ||
110 | { | ||
111 | unsigned int count; | ||
112 | unsigned int i; | ||
113 | unsigned int j; | ||
114 | unsigned int len; | ||
115 | int cnt; | ||
116 | unsigned int pos; | ||
117 | unsigned int temps[8]; | ||
118 | int slash; | ||
119 | struct IPv4NetworkSet *result; | ||
120 | |||
121 | if (NULL == routeList) | ||
122 | return NULL; | ||
123 | len = strlen (routeList); | ||
124 | if (0 == len) | ||
125 | return NULL; | ||
126 | count = 0; | ||
127 | for (i = 0; i < len; i++) | ||
128 | if (routeList[i] == ';') | ||
129 | count++; | ||
130 | result = GNUNET_malloc (sizeof (struct IPv4NetworkSet) * (count + 1)); | ||
131 | i = 0; | ||
132 | pos = 0; | ||
133 | while (i < count) | ||
134 | { | ||
135 | cnt = | ||
136 | SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0], | ||
137 | &temps[1], &temps[2], &temps[3], &temps[4], &temps[5], | ||
138 | &temps[6], &temps[7]); | ||
139 | if (8 == cnt) | ||
140 | { | ||
141 | for (j = 0; j < 8; j++) | ||
142 | if (temps[j] > 0xFF) | ||
143 | { | ||
144 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), | ||
145 | &routeList[pos]); | ||
146 | GNUNET_free (result); | ||
147 | return NULL; | ||
148 | } | ||
149 | result[i].network.s_addr = | ||
150 | htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + | ||
151 | temps[3]); | ||
152 | result[i].netmask.s_addr = | ||
153 | htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) + | ||
154 | temps[7]); | ||
155 | while (routeList[pos] != ';') | ||
156 | pos++; | ||
157 | pos++; | ||
158 | i++; | ||
159 | continue; | ||
160 | } | ||
161 | /* try second notation */ | ||
162 | cnt = | ||
163 | SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1], | ||
164 | &temps[2], &temps[3], &slash); | ||
165 | if (5 == cnt) | ||
166 | { | ||
167 | for (j = 0; j < 4; j++) | ||
168 | if (temps[j] > 0xFF) | ||
169 | { | ||
170 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), | ||
171 | &routeList[pos]); | ||
172 | GNUNET_free (result); | ||
173 | return NULL; | ||
174 | } | ||
175 | result[i].network.s_addr = | ||
176 | htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + | ||
177 | temps[3]); | ||
178 | if ((slash <= 32) && (slash >= 0)) | ||
179 | { | ||
180 | result[i].netmask.s_addr = 0; | ||
181 | while (slash > 0) | ||
182 | { | ||
183 | result[i].netmask.s_addr = | ||
184 | (result[i].netmask.s_addr >> 1) + 0x80000000; | ||
185 | slash--; | ||
186 | } | ||
187 | result[i].netmask.s_addr = htonl (result[i].netmask.s_addr); | ||
188 | while (';' != routeList[pos]) | ||
189 | pos++; | ||
190 | pos++; | ||
191 | i++; | ||
192 | continue; | ||
193 | } | ||
194 | else | ||
195 | { | ||
196 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
197 | _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."), | ||
198 | slash); | ||
199 | GNUNET_free (result); | ||
200 | return NULL; /* error */ | ||
201 | } | ||
202 | } | ||
203 | /* try third notation */ | ||
204 | slash = 32; | ||
205 | cnt = | ||
206 | SSCANF (&routeList[pos], "%u.%u.%u.%u;", &temps[0], &temps[1], | ||
207 | &temps[2], &temps[3]); | ||
208 | if (4 == cnt) | ||
209 | { | ||
210 | for (j = 0; j < 4; j++) | ||
211 | if (temps[j] > 0xFF) | ||
212 | { | ||
213 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), | ||
214 | &routeList[pos]); | ||
215 | GNUNET_free (result); | ||
216 | return NULL; | ||
217 | } | ||
218 | result[i].network.s_addr = | ||
219 | htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + | ||
220 | temps[3]); | ||
221 | result[i].netmask.s_addr = 0; | ||
222 | while (slash > 0) | ||
223 | { | ||
224 | result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000; | ||
225 | slash--; | ||
226 | } | ||
227 | result[i].netmask.s_addr = htonl (result[i].netmask.s_addr); | ||
228 | while (routeList[pos] != ';') | ||
229 | pos++; | ||
230 | pos++; | ||
231 | i++; | ||
232 | continue; | ||
233 | } | ||
234 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), | ||
235 | &routeList[pos]); | ||
236 | GNUNET_free (result); | ||
237 | return NULL; /* error */ | ||
238 | } | ||
239 | if (pos < strlen (routeList)) | ||
240 | { | ||
241 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), | ||
242 | &routeList[pos]); | ||
243 | GNUNET_free (result); | ||
244 | return NULL; /* oops */ | ||
245 | } | ||
246 | return result; /* ok */ | ||
247 | } | ||
248 | |||
249 | |||
250 | /** | ||
251 | * Parse a network specification. The argument specifies | ||
252 | * a list of networks. The format is | ||
253 | * <tt>[network/netmask;]*</tt> (no whitespace, must be terminated | ||
254 | * with a semicolon). The network must be given in colon-hex | ||
255 | * notation. The netmask must be given in CIDR notation (/16) or | ||
256 | * can be omitted to specify a single host. | ||
257 | * | ||
258 | * @param routeListX a string specifying the forbidden networks | ||
259 | * @return the converted list, NULL if the synatx is flawed | ||
260 | */ | ||
261 | static struct IPv6NetworkSet * | ||
262 | parse_ipv6_specification (const char *routeListX) | ||
263 | { | ||
264 | unsigned int count; | ||
265 | unsigned int i; | ||
266 | unsigned int len; | ||
267 | unsigned int pos; | ||
268 | int start; | ||
269 | int slash; | ||
270 | int ret; | ||
271 | char *routeList; | ||
272 | struct IPv6NetworkSet *result; | ||
273 | unsigned int bits; | ||
274 | unsigned int off; | ||
275 | int save; | ||
276 | |||
277 | if (NULL == routeListX) | ||
278 | return NULL; | ||
279 | len = strlen (routeListX); | ||
280 | if (0 == len) | ||
281 | return NULL; | ||
282 | routeList = GNUNET_strdup (routeListX); | ||
283 | count = 0; | ||
284 | for (i = 0; i < len; i++) | ||
285 | if (';' == routeList[i]) | ||
286 | count++; | ||
287 | if (';' != routeList[len - 1]) | ||
288 | { | ||
289 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
290 | _("Invalid network notation (does not end with ';': `%s')\n"), | ||
291 | routeList); | ||
292 | GNUNET_free (routeList); | ||
293 | return NULL; | ||
294 | } | ||
295 | |||
296 | result = GNUNET_malloc (sizeof (struct IPv6NetworkSet) * (count + 1)); | ||
297 | i = 0; | ||
298 | pos = 0; | ||
299 | while (i < count) | ||
300 | { | ||
301 | start = pos; | ||
302 | while (';' != routeList[pos]) | ||
303 | pos++; | ||
304 | slash = pos; | ||
305 | while ((slash >= start) && (routeList[slash] != '/')) | ||
306 | slash--; | ||
307 | if (slash < start) | ||
308 | { | ||
309 | memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr)); | ||
310 | slash = pos; | ||
311 | } | ||
312 | else | ||
313 | { | ||
314 | routeList[pos] = '\0'; | ||
315 | ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask); | ||
316 | if (ret <= 0) | ||
317 | { | ||
318 | save = errno; | ||
319 | if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128)) | ||
320 | { | ||
321 | if (0 == ret) | ||
322 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong format `%s' for netmask\n"), | ||
323 | &routeList[slash + 1]); | ||
324 | else | ||
325 | { | ||
326 | errno = save; | ||
327 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton"); | ||
328 | } | ||
329 | GNUNET_free (result); | ||
330 | GNUNET_free (routeList); | ||
331 | return NULL; | ||
332 | } | ||
333 | off = 0; | ||
334 | while (bits > 8) | ||
335 | { | ||
336 | result[i].netmask.s6_addr[off++] = 0xFF; | ||
337 | bits -= 8; | ||
338 | } | ||
339 | while (bits > 0) | ||
340 | { | ||
341 | result[i].netmask.s6_addr[off] = | ||
342 | (result[i].netmask.s6_addr[off] >> 1) + 0x80; | ||
343 | bits--; | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | routeList[slash] = '\0'; | ||
348 | ret = inet_pton (AF_INET6, &routeList[start], &result[i].network); | ||
349 | if (ret <= 0) | ||
350 | { | ||
351 | if (0 == ret) | ||
352 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong format `%s' for network\n"), | ||
353 | &routeList[slash + 1]); | ||
354 | else | ||
355 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton"); | ||
356 | GNUNET_free (result); | ||
357 | GNUNET_free (routeList); | ||
358 | return NULL; | ||
359 | } | ||
360 | pos++; | ||
361 | i++; | ||
362 | } | ||
363 | GNUNET_free (routeList); | ||
364 | return result; | ||
365 | } | ||
366 | |||
367 | |||
368 | /** | ||
369 | * Check if the given IP address is in the list of IP addresses. | 64 | * Check if the given IP address is in the list of IP addresses. |
370 | * | 65 | * |
371 | * @param list a list of networks | 66 | * @param list a list of networks |
@@ -373,7 +68,7 @@ parse_ipv6_specification (const char *routeListX) | |||
373 | * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is | 68 | * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is |
374 | */ | 69 | */ |
375 | static int | 70 | static int |
376 | check_ipv4_listed (const struct IPv4NetworkSet *list, const struct in_addr *add) | 71 | check_ipv4_listed (const struct GNUNET_STRINGS_IPv4NetworkPolicy *list, const struct in_addr *add) |
377 | { | 72 | { |
378 | unsigned int i; | 73 | unsigned int i; |
379 | 74 | ||
@@ -399,7 +94,7 @@ check_ipv4_listed (const struct IPv4NetworkSet *list, const struct in_addr *add) | |||
399 | * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is | 94 | * @return GNUNET_NO if the IP is not in the list, GNUNET_YES if it it is |
400 | */ | 95 | */ |
401 | static int | 96 | static int |
402 | check_ipv6_listed (const struct IPv6NetworkSet *list, const struct in6_addr *ip) | 97 | check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list, const struct in6_addr *ip) |
403 | { | 98 | { |
404 | unsigned int i; | 99 | unsigned int i; |
405 | unsigned int j; | 100 | unsigned int j; |
@@ -467,24 +162,24 @@ struct GNUNET_SERVICE_Context | |||
467 | /** | 162 | /** |
468 | * IPv4 addresses that are not allowed to connect. | 163 | * IPv4 addresses that are not allowed to connect. |
469 | */ | 164 | */ |
470 | struct IPv4NetworkSet *v4_denied; | 165 | struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_denied; |
471 | 166 | ||
472 | /** | 167 | /** |
473 | * IPv6 addresses that are not allowed to connect. | 168 | * IPv6 addresses that are not allowed to connect. |
474 | */ | 169 | */ |
475 | struct IPv6NetworkSet *v6_denied; | 170 | struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_denied; |
476 | 171 | ||
477 | /** | 172 | /** |
478 | * IPv4 addresses that are allowed to connect (if not | 173 | * IPv4 addresses that are allowed to connect (if not |
479 | * set, all are allowed). | 174 | * set, all are allowed). |
480 | */ | 175 | */ |
481 | struct IPv4NetworkSet *v4_allowed; | 176 | struct GNUNET_STRINGS_IPv4NetworkPolicy *v4_allowed; |
482 | 177 | ||
483 | /** | 178 | /** |
484 | * IPv6 addresses that are allowed to connect (if not | 179 | * IPv6 addresses that are allowed to connect (if not |
485 | * set, all are allowed). | 180 | * set, all are allowed). |
486 | */ | 181 | */ |
487 | struct IPv6NetworkSet *v6_allowed; | 182 | struct GNUNET_STRINGS_IPv6NetworkPolicy *v6_allowed; |
488 | 183 | ||
489 | /** | 184 | /** |
490 | * My (default) message handlers. Adjusted copy | 185 | * My (default) message handlers. Adjusted copy |
@@ -707,7 +402,7 @@ get_pid_file_name (struct GNUNET_SERVICE_Context *sctx) | |||
707 | * no ACL configured) | 402 | * no ACL configured) |
708 | */ | 403 | */ |
709 | static int | 404 | static int |
710 | process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx, | 405 | process_acl4 (struct GNUNET_STRINGS_IPv4NetworkPolicy **ret, struct GNUNET_SERVICE_Context *sctx, |
711 | const char *option) | 406 | const char *option) |
712 | { | 407 | { |
713 | char *opt; | 408 | char *opt; |
@@ -721,7 +416,7 @@ process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx, | |||
721 | GNUNET_CONFIGURATION_get_value_string (sctx->cfg, | 416 | GNUNET_CONFIGURATION_get_value_string (sctx->cfg, |
722 | sctx->service_name, | 417 | sctx->service_name, |
723 | option, &opt)); | 418 | option, &opt)); |
724 | if (NULL == (*ret = parse_ipv4_specification (opt))) | 419 | if (NULL == (*ret = GNUNET_STRINGS_parse_ipv4_policy (opt))) |
725 | { | 420 | { |
726 | LOG (GNUNET_ERROR_TYPE_WARNING, | 421 | LOG (GNUNET_ERROR_TYPE_WARNING, |
727 | _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"), | 422 | _("Could not parse IPv4 network specification `%s' for `%s:%s'\n"), |
@@ -744,7 +439,7 @@ process_acl4 (struct IPv4NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx, | |||
744 | * no ACL configured) | 439 | * no ACL configured) |
745 | */ | 440 | */ |
746 | static int | 441 | static int |
747 | process_acl6 (struct IPv6NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx, | 442 | process_acl6 (struct GNUNET_STRINGS_IPv6NetworkPolicy **ret, struct GNUNET_SERVICE_Context *sctx, |
748 | const char *option) | 443 | const char *option) |
749 | { | 444 | { |
750 | char *opt; | 445 | char *opt; |
@@ -758,7 +453,7 @@ process_acl6 (struct IPv6NetworkSet **ret, struct GNUNET_SERVICE_Context *sctx, | |||
758 | GNUNET_CONFIGURATION_get_value_string (sctx->cfg, | 453 | GNUNET_CONFIGURATION_get_value_string (sctx->cfg, |
759 | sctx->service_name, | 454 | sctx->service_name, |
760 | option, &opt)); | 455 | option, &opt)); |
761 | if (NULL == (*ret = parse_ipv6_specification (opt))) | 456 | if (NULL == (*ret = GNUNET_STRINGS_parse_ipv6_policy (opt))) |
762 | { | 457 | { |
763 | LOG (GNUNET_ERROR_TYPE_WARNING, | 458 | LOG (GNUNET_ERROR_TYPE_WARNING, |
764 | _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"), | 459 | _("Could not parse IPv6 network specification `%s' for `%s:%s'\n"), |
diff --git a/src/util/strings.c b/src/util/strings.c index 581ac013d..c50669e62 100644 --- a/src/util/strings.c +++ b/src/util/strings.c | |||
@@ -1328,4 +1328,285 @@ GNUNET_STRINGS_get_utf8_args (int argc, char *const *argv, int *u8argc, char *co | |||
1328 | #endif | 1328 | #endif |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | |||
1332 | /** | ||
1333 | * Parse an IPv4 network policy. The argument specifies a list of | ||
1334 | * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace, | ||
1335 | * must be terminated with a semicolon). The network must be given in | ||
1336 | * dotted-decimal notation. The netmask can be given in CIDR notation | ||
1337 | * (/16) or in dotted-decimal (/255.255.0.0). | ||
1338 | * | ||
1339 | * @param routeList a string specifying the IPv4 subnets | ||
1340 | * @return the converted list, terminated with all zeros; | ||
1341 | * NULL if the synatx is flawed | ||
1342 | */ | ||
1343 | struct GNUNET_STRINGS_IPv4NetworkPolicy * | ||
1344 | GNUNET_STRINGS_parse_ipv4_policy (const char *routeList) | ||
1345 | { | ||
1346 | unsigned int count; | ||
1347 | unsigned int i; | ||
1348 | unsigned int j; | ||
1349 | unsigned int len; | ||
1350 | int cnt; | ||
1351 | unsigned int pos; | ||
1352 | unsigned int temps[8]; | ||
1353 | int slash; | ||
1354 | struct GNUNET_STRINGS_IPv4NetworkPolicy *result; | ||
1355 | |||
1356 | if (NULL == routeList) | ||
1357 | return NULL; | ||
1358 | len = strlen (routeList); | ||
1359 | if (0 == len) | ||
1360 | return NULL; | ||
1361 | count = 0; | ||
1362 | for (i = 0; i < len; i++) | ||
1363 | if (routeList[i] == ';') | ||
1364 | count++; | ||
1365 | result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv4NetworkPolicy) * (count + 1)); | ||
1366 | i = 0; | ||
1367 | pos = 0; | ||
1368 | while (i < count) | ||
1369 | { | ||
1370 | cnt = | ||
1371 | SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0], | ||
1372 | &temps[1], &temps[2], &temps[3], &temps[4], &temps[5], | ||
1373 | &temps[6], &temps[7]); | ||
1374 | if (8 == cnt) | ||
1375 | { | ||
1376 | for (j = 0; j < 8; j++) | ||
1377 | if (temps[j] > 0xFF) | ||
1378 | { | ||
1379 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), | ||
1380 | &routeList[pos]); | ||
1381 | GNUNET_free (result); | ||
1382 | return NULL; | ||
1383 | } | ||
1384 | result[i].network.s_addr = | ||
1385 | htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + | ||
1386 | temps[3]); | ||
1387 | result[i].netmask.s_addr = | ||
1388 | htonl ((temps[4] << 24) + (temps[5] << 16) + (temps[6] << 8) + | ||
1389 | temps[7]); | ||
1390 | while (routeList[pos] != ';') | ||
1391 | pos++; | ||
1392 | pos++; | ||
1393 | i++; | ||
1394 | continue; | ||
1395 | } | ||
1396 | /* try second notation */ | ||
1397 | cnt = | ||
1398 | SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1], | ||
1399 | &temps[2], &temps[3], &slash); | ||
1400 | if (5 == cnt) | ||
1401 | { | ||
1402 | for (j = 0; j < 4; j++) | ||
1403 | if (temps[j] > 0xFF) | ||
1404 | { | ||
1405 | LOG (GNUNET_ERROR_TYPE_ERROR, _("Invalid format for IP: `%s'\n"), | ||
1406 | &routeList[pos]); | ||
1407 | GNUNET_free (result); | ||
1408 | return NULL; | ||
1409 | } | ||
1410 | result[i].network.s_addr = | ||
1411 | htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + | ||
1412 | temps[3]); | ||
1413 | if ((slash <= 32) && (slash >= 0)) | ||
1414 | { | ||
1415 | result[i].netmask.s_addr = 0; | ||
1416 | while (slash > 0) | ||
1417 | { | ||
1418 | result[i].netmask.s_addr = | ||
1419 | (result[i].netmask.s_addr >> 1) + 0x80000000; | ||
1420 | slash--; | ||
1421 | } | ||
1422 | result[i].netmask.s_addr = htonl (result[i].netmask.s_addr); | ||
1423 | while (';' != routeList[pos]) | ||
1424 | pos++; | ||
1425 | pos++; | ||
1426 | i++; | ||
1427 | continue; | ||
1428 | } | ||
1429 | else | ||
1430 | { | ||
1431 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1432 | _("Invalid network notation ('/%d' is not legal in IPv4 CIDR)."), | ||
1433 | slash); | ||
1434 | GNUNET_free (result); | ||
1435 | return NULL; /* error */ | ||
1436 | } | ||
1437 | } | ||
1438 | /* try third notation */ | ||
1439 | slash = 32; | ||
1440 | cnt = | ||
1441 | SSCANF (&routeList[pos], | ||
1442 | "%u.%u.%u.%u;", | ||
1443 | &temps[0], | ||
1444 | &temps[1], | ||
1445 | &temps[2], | ||
1446 | &temps[3]); | ||
1447 | if (4 == cnt) | ||
1448 | { | ||
1449 | for (j = 0; j < 4; j++) | ||
1450 | if (temps[j] > 0xFF) | ||
1451 | { | ||
1452 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1453 | _("Invalid format for IP: `%s'\n"), | ||
1454 | &routeList[pos]); | ||
1455 | GNUNET_free (result); | ||
1456 | return NULL; | ||
1457 | } | ||
1458 | result[i].network.s_addr = | ||
1459 | htonl ((temps[0] << 24) + (temps[1] << 16) + (temps[2] << 8) + | ||
1460 | temps[3]); | ||
1461 | result[i].netmask.s_addr = 0; | ||
1462 | while (slash > 0) | ||
1463 | { | ||
1464 | result[i].netmask.s_addr = (result[i].netmask.s_addr >> 1) + 0x80000000; | ||
1465 | slash--; | ||
1466 | } | ||
1467 | result[i].netmask.s_addr = htonl (result[i].netmask.s_addr); | ||
1468 | while (routeList[pos] != ';') | ||
1469 | pos++; | ||
1470 | pos++; | ||
1471 | i++; | ||
1472 | continue; | ||
1473 | } | ||
1474 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1475 | _("Invalid format for IP: `%s'\n"), | ||
1476 | &routeList[pos]); | ||
1477 | GNUNET_free (result); | ||
1478 | return NULL; /* error */ | ||
1479 | } | ||
1480 | if (pos < strlen (routeList)) | ||
1481 | { | ||
1482 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1483 | _("Invalid format for IP: `%s'\n"), | ||
1484 | &routeList[pos]); | ||
1485 | GNUNET_free (result); | ||
1486 | return NULL; /* oops */ | ||
1487 | } | ||
1488 | return result; /* ok */ | ||
1489 | } | ||
1490 | |||
1491 | |||
1492 | /** | ||
1493 | * Parse an IPv6 network policy. The argument specifies a list of | ||
1494 | * subnets. The format is <tt>[network/netmask;]*</tt> (no whitespace, | ||
1495 | * must be terminated with a semicolon). The network must be given in | ||
1496 | * colon-hex notation. The netmask must be given in CIDR notation | ||
1497 | * (/16) or can be omitted to specify a single host. | ||
1498 | * | ||
1499 | * @param routeListX a string specifying the policy | ||
1500 | * @return the converted list, 0-terminated, NULL if the synatx is flawed | ||
1501 | */ | ||
1502 | struct GNUNET_STRINGS_IPv6NetworkPolicy * | ||
1503 | GNUNET_STRINGS_parse_ipv6_policy (const char *routeListX) | ||
1504 | { | ||
1505 | unsigned int count; | ||
1506 | unsigned int i; | ||
1507 | unsigned int len; | ||
1508 | unsigned int pos; | ||
1509 | int start; | ||
1510 | int slash; | ||
1511 | int ret; | ||
1512 | char *routeList; | ||
1513 | struct GNUNET_STRINGS_IPv6NetworkPolicy *result; | ||
1514 | unsigned int bits; | ||
1515 | unsigned int off; | ||
1516 | int save; | ||
1517 | |||
1518 | if (NULL == routeListX) | ||
1519 | return NULL; | ||
1520 | len = strlen (routeListX); | ||
1521 | if (0 == len) | ||
1522 | return NULL; | ||
1523 | routeList = GNUNET_strdup (routeListX); | ||
1524 | count = 0; | ||
1525 | for (i = 0; i < len; i++) | ||
1526 | if (';' == routeList[i]) | ||
1527 | count++; | ||
1528 | if (';' != routeList[len - 1]) | ||
1529 | { | ||
1530 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1531 | _("Invalid network notation (does not end with ';': `%s')\n"), | ||
1532 | routeList); | ||
1533 | GNUNET_free (routeList); | ||
1534 | return NULL; | ||
1535 | } | ||
1536 | |||
1537 | result = GNUNET_malloc (sizeof (struct GNUNET_STRINGS_IPv6NetworkPolicy) * (count + 1)); | ||
1538 | i = 0; | ||
1539 | pos = 0; | ||
1540 | while (i < count) | ||
1541 | { | ||
1542 | start = pos; | ||
1543 | while (';' != routeList[pos]) | ||
1544 | pos++; | ||
1545 | slash = pos; | ||
1546 | while ((slash >= start) && (routeList[slash] != '/')) | ||
1547 | slash--; | ||
1548 | if (slash < start) | ||
1549 | { | ||
1550 | memset (&result[i].netmask, 0xFF, sizeof (struct in6_addr)); | ||
1551 | slash = pos; | ||
1552 | } | ||
1553 | else | ||
1554 | { | ||
1555 | routeList[pos] = '\0'; | ||
1556 | ret = inet_pton (AF_INET6, &routeList[slash + 1], &result[i].netmask); | ||
1557 | if (ret <= 0) | ||
1558 | { | ||
1559 | save = errno; | ||
1560 | if ((1 != SSCANF (&routeList[slash + 1], "%u", &bits)) || (bits >= 128)) | ||
1561 | { | ||
1562 | if (0 == ret) | ||
1563 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1564 | _("Wrong format `%s' for netmask\n"), | ||
1565 | &routeList[slash + 1]); | ||
1566 | else | ||
1567 | { | ||
1568 | errno = save; | ||
1569 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "inet_pton"); | ||
1570 | } | ||
1571 | GNUNET_free (result); | ||
1572 | GNUNET_free (routeList); | ||
1573 | return NULL; | ||
1574 | } | ||
1575 | off = 0; | ||
1576 | while (bits > 8) | ||
1577 | { | ||
1578 | result[i].netmask.s6_addr[off++] = 0xFF; | ||
1579 | bits -= 8; | ||
1580 | } | ||
1581 | while (bits > 0) | ||
1582 | { | ||
1583 | result[i].netmask.s6_addr[off] = | ||
1584 | (result[i].netmask.s6_addr[off] >> 1) + 0x80; | ||
1585 | bits--; | ||
1586 | } | ||
1587 | } | ||
1588 | } | ||
1589 | routeList[slash] = '\0'; | ||
1590 | ret = inet_pton (AF_INET6, &routeList[start], &result[i].network); | ||
1591 | if (ret <= 0) | ||
1592 | { | ||
1593 | if (0 == ret) | ||
1594 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1595 | _("Wrong format `%s' for network\n"), | ||
1596 | &routeList[slash + 1]); | ||
1597 | else | ||
1598 | LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, | ||
1599 | "inet_pton"); | ||
1600 | GNUNET_free (result); | ||
1601 | GNUNET_free (routeList); | ||
1602 | return NULL; | ||
1603 | } | ||
1604 | pos++; | ||
1605 | i++; | ||
1606 | } | ||
1607 | GNUNET_free (routeList); | ||
1608 | return result; | ||
1609 | } | ||
1610 | |||
1611 | |||
1331 | /* end of strings.c */ | 1612 | /* end of strings.c */ |