| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: rfc6056.c,v 1.7 2012/06/21 10:30:47 yamt Exp $ */ | | 1 | /* $NetBSD: rfc6056.c,v 1.8 2012/06/21 10:35:28 yamt Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright 2011 Vlad Balan | | 4 | * Copyright 2011 Vlad Balan |
5 | * | | 5 | * |
6 | * Written by Vlad Balan for the NetBSD Foundation. | | 6 | * Written by Vlad Balan for the NetBSD Foundation. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
| @@ -24,27 +24,27 @@ | | | @@ -24,27 +24,27 @@ |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
27 | * SUCH DAMAGE. | | 27 | * SUCH DAMAGE. |
28 | * | | 28 | * |
29 | */ | | 29 | */ |
30 | | | 30 | |
31 | /* | | 31 | /* |
32 | * see: | | 32 | * see: |
33 | * RFC 6056 Recommendations for Transport-Protocol Port Randomization | | 33 | * RFC 6056 Recommendations for Transport-Protocol Port Randomization |
34 | */ | | 34 | */ |
35 | | | 35 | |
36 | #include <sys/cdefs.h> | | 36 | #include <sys/cdefs.h> |
37 | __KERNEL_RCSID(0, "$NetBSD: rfc6056.c,v 1.7 2012/06/21 10:30:47 yamt Exp $"); | | 37 | __KERNEL_RCSID(0, "$NetBSD: rfc6056.c,v 1.8 2012/06/21 10:35:28 yamt Exp $"); |
38 | | | 38 | |
39 | #include "opt_inet.h" | | 39 | #include "opt_inet.h" |
40 | | | 40 | |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/errno.h> | | 42 | #include <sys/errno.h> |
43 | #include <sys/kauth.h> | | 43 | #include <sys/kauth.h> |
44 | #include <sys/uidinfo.h> | | 44 | #include <sys/uidinfo.h> |
45 | #include <sys/domain.h> | | 45 | #include <sys/domain.h> |
46 | #include <sys/md5.h> | | 46 | #include <sys/md5.h> |
47 | #include <sys/cprng.h> | | 47 | #include <sys/cprng.h> |
48 | | | 48 | |
49 | #include <net/if.h> | | 49 | #include <net/if.h> |
50 | #include <net/route.h> | | 50 | #include <net/route.h> |
| @@ -349,67 +349,55 @@ check_suitable_port(uint16_t port, struc | | | @@ -349,67 +349,55 @@ check_suitable_port(uint16_t port, struc |
349 | } | | 349 | } |
350 | break; | | 350 | break; |
351 | } | | 351 | } |
352 | #endif | | 352 | #endif |
353 | default: | | 353 | default: |
354 | DPRINTF("%s unknown address family\n", __func__); | | 354 | DPRINTF("%s unknown address family\n", __func__); |
355 | return false; | | 355 | return false; |
356 | } | | 356 | } |
357 | return false; | | 357 | return false; |
358 | } | | 358 | } |
359 | | | 359 | |
360 | /* This is the default BSD algorithm, as described in RFC 6056 */ | | 360 | /* This is the default BSD algorithm, as described in RFC 6056 */ |
361 | static int | | 361 | static int |
362 | algo_bsd(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, | | 362 | algo_bsd(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, kauth_cred_t cred) |
363 | kauth_cred_t cred) | | | |
364 | { | | 363 | { |
365 | uint16_t count, num_ephemeral; | | 364 | uint16_t count; |
366 | uint16_t mymin, mymax, lastport; | | 365 | uint16_t mymin, mymax, lastport; |
367 | uint16_t *next_ephemeral; | | 366 | uint16_t *next_ephemeral; |
368 | int error; | | 367 | int error; |
369 | | | 368 | |
370 | DPRINTF("%s called\n", __func__); | | 369 | DPRINTF("%s called\n", __func__); |
371 | | | | |
372 | error = pcb_getports(inp_hdr, &lastport, &mymin, &mymax, | | 370 | error = pcb_getports(inp_hdr, &lastport, &mymin, &mymax, |
373 | &next_ephemeral, algo); | | 371 | &next_ephemeral, algo); |
374 | if (error) | | 372 | if (error) |
375 | return error; | | 373 | return error; |
376 | | | 374 | count = mymax - mymin + 1; |
377 | /* Ephemeral port selection function */ | | | |
378 | num_ephemeral = mymax - mymin + 1; | | | |
379 | | | | |
380 | if (*next_ephemeral == 0) | | | |
381 | *next_ephemeral = mymax; | | | |
382 | | | | |
383 | count = num_ephemeral; | | | |
384 | do { | | 375 | do { |
385 | uint16_t myport = *next_ephemeral; | | 376 | uint16_t myport = *next_ephemeral; |
386 | if (*next_ephemeral <= mymin) | | | |
387 | *next_ephemeral = mymax; | | | |
388 | else | | | |
389 | (*next_ephemeral)--; | | | |
390 | | | 377 | |
| | | 378 | if (myport < mymin || mymax < myport) |
| | | 379 | myport = mymax; |
| | | 380 | *next_ephemeral = myport - 1; |
391 | if (check_suitable_port(myport, inp_hdr, cred)) { | | 381 | if (check_suitable_port(myport, inp_hdr, cred)) { |
392 | *port = myport; | | 382 | *port = myport; |
393 | DPRINTF("%s returning port %d\n", __func__, *port); | | 383 | DPRINTF("%s returning port %d\n", __func__, *port); |
394 | return 0; | | 384 | return 0; |
395 | } | | 385 | } |
396 | count--; | | 386 | count--; |
397 | | | | |
398 | } while (count > 0); | | 387 | } while (count > 0); |
399 | | | 388 | |
400 | DPRINTF("%s returning EINVAL\n", __func__); | | 389 | DPRINTF("%s returning EAGAIN\n", __func__); |
401 | | | 390 | return EAGAIN; |
402 | return EINVAL; | | | |
403 | } | | 391 | } |
404 | | | 392 | |
405 | /* | | 393 | /* |
406 | * The straightforward algorithm that calls random() in order to | | 394 | * The straightforward algorithm that calls random() in order to |
407 | * compute the increment to the next port number. | | 395 | * compute the increment to the next port number. |
408 | */ | | 396 | */ |
409 | static int | | 397 | static int |
410 | algo_random_start(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, | | 398 | algo_random_start(int algo, uint16_t *port, struct inpcb_hdr *inp_hdr, |
411 | kauth_cred_t cred) | | 399 | kauth_cred_t cred) |
412 | { | | 400 | { |
413 | uint16_t count, num_ephemeral; | | 401 | uint16_t count, num_ephemeral; |
414 | uint16_t mymin, mymax, lastport; | | 402 | uint16_t mymin, mymax, lastport; |
415 | uint16_t *next_ephemeral; | | 403 | uint16_t *next_ephemeral; |
| @@ -806,39 +794,38 @@ rfc6056_randport(uint16_t *port, struct | | | @@ -806,39 +794,38 @@ rfc6056_randport(uint16_t *port, struct |
806 | DPRINTF("local addr: %s\n", ip6_sprintf(&in6p->in6p_laddr)); | | 794 | DPRINTF("local addr: %s\n", ip6_sprintf(&in6p->in6p_laddr)); |
807 | DPRINTF("local port: %d\n", in6p->in6p_lport); | | 795 | DPRINTF("local port: %d\n", in6p->in6p_lport); |
808 | DPRINTF("foreign addr: %s\n", ip6_sprintf(&in6p->in6p_faddr)); | | 796 | DPRINTF("foreign addr: %s\n", ip6_sprintf(&in6p->in6p_faddr)); |
809 | DPRINTF("foreign port: %d\n", in6p->in6p_fport); | | 797 | DPRINTF("foreign port: %d\n", in6p->in6p_fport); |
810 | break; | | 798 | break; |
811 | } | | 799 | } |
812 | #endif | | 800 | #endif |
813 | default: | | 801 | default: |
814 | break; | | 802 | break; |
815 | } | | 803 | } |
816 | | | 804 | |
817 | DPRINTF("%s rfc6056algo = %d\n", __func__, algo); | | 805 | DPRINTF("%s rfc6056algo = %d\n", __func__, algo); |
818 | | | 806 | |
819 | | | | |
820 | error = (*algos[algo].func)(algo, &lport, inp_hdr, cred); | | 807 | error = (*algos[algo].func)(algo, &lport, inp_hdr, cred); |
821 | if (error == 0) | | 808 | if (error == 0) { |
822 | *port = lport; | | 809 | *port = lport; |
823 | else { | | 810 | } else if (error != EAGAIN) { |
824 | uint16_t lastport, mymin, mymax, *pnext_ephemeral; | | 811 | uint16_t lastport, mymin, mymax, *pnext_ephemeral; |
| | | 812 | |
825 | error = pcb_getports(inp_hdr, &lastport, &mymin, | | 813 | error = pcb_getports(inp_hdr, &lastport, &mymin, |
826 | &mymax, &pnext_ephemeral, algo); | | 814 | &mymax, &pnext_ephemeral, algo); |
827 | if (error) | | 815 | if (error) |
828 | return error; | | 816 | return error; |
829 | *port = lastport - 1; | | 817 | *port = lastport - 1; |
830 | } | | 818 | } |
831 | | | | |
832 | return error; | | 819 | return error; |
833 | } | | 820 | } |
834 | | | 821 | |
835 | /* Sets the algorithm to be used globally */ | | 822 | /* Sets the algorithm to be used globally */ |
836 | static int | | 823 | static int |
837 | rfc6056_algo_name_select(const char *name, int *algo) | | 824 | rfc6056_algo_name_select(const char *name, int *algo) |
838 | { | | 825 | { |
839 | size_t ai; | | 826 | size_t ai; |
840 | | | 827 | |
841 | DPRINTF("%s called\n", __func__); | | 828 | DPRINTF("%s called\n", __func__); |
842 | | | 829 | |
843 | for (ai = 0; ai < NALGOS; ai++) | | 830 | for (ai = 0; ai < NALGOS; ai++) |
844 | if (strcmp(algos[ai].name, name) == 0) { | | 831 | if (strcmp(algos[ai].name, name) == 0) { |