0018-traceroute-Subprivileged-use-case.patch 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. From 64ee5ba5cad6298f72271539cb96e2de164dfc2f Mon Sep 17 00:00:00 2001
  2. From: Mats Erik Andersson <gnu@gisladisker.se>
  3. Date: Tue, 16 Feb 2016 23:29:25 +0100
  4. Subject: [PATCH 18/60] traceroute: Subprivileged use case.
  5. A fallback for ICMP tracing relevant to GNU/Linux is implemented,
  6. allowing a rudimentary but suid-less use case.
  7. ---
  8. ChangeLog | 18 ++++++++++++++++++
  9. src/traceroute.c | 30 +++++++++++++++++++++++++++++-
  10. 2 files changed, 47 insertions(+), 1 deletion(-)
  11. diff --git a/ChangeLog b/ChangeLog
  12. index e79308bc..f01a330c 100644
  13. --- a/ChangeLog
  14. +++ b/ChangeLog
  15. @@ -1,3 +1,21 @@
  16. +2016-02-16 Mats Erik Andersson <gnu@gisladisker.se>
  17. +
  18. + traceroute: Subprivileged use case.
  19. + A fallback for ICMP tracing relevant to GNU/Linux is implemented,
  20. + allowing a rudimentary but suid-less use case. The ability to
  21. + identify intermediary hosts is missing, due to the crippled
  22. + capability of receiving ICMP packets other than ICMP_ECHOREPLY.
  23. +
  24. + * src/traceroute.c (struct trace): New member `no_ident'.
  25. + (trace_init): Initiate `t->no_ident'.
  26. + <type TRACE_ICMP or TRACE_UDP>: In case a raw socket for an ICMP
  27. + protocol fails, fall back to a datagram socket.
  28. + (trace_read) <type TRACE_ICMP>: Short circuit `ic->icmp_id != pid'
  29. + with the conditional `t->no_ident == 0'.
  30. + (trace_write) <type TRACE_ICMP>: New variable I. Initialize HDR
  31. + to its full extent. If `t->no_ident' is non-zero, insert our
  32. + intended target as payload of HDR for trace identification.
  33. +
  34. 2016-02-12 Mats Erik Andersson <gnu@gisladisker.se>
  35. ping: Implement subprivileged echo method.
  36. diff --git a/src/traceroute.c b/src/traceroute.c
  37. index 785dc6f2..2a56a53d 100644
  38. --- a/src/traceroute.c
  39. +++ b/src/traceroute.c
  40. @@ -75,6 +75,7 @@ typedef struct trace
  41. {
  42. int icmpfd, udpfd;
  43. enum trace_type type;
  44. + int no_ident;
  45. struct sockaddr_in to, from;
  46. int ttl;
  47. struct timeval tsent;
  48. @@ -476,6 +477,7 @@ trace_init (trace_t * t, const struct sockaddr_in to,
  49. t->type = type;
  50. t->to = to;
  51. t->ttl = opt_ttl;
  52. + t->no_ident = 0;
  53. if (t->type == TRACE_UDP)
  54. {
  55. @@ -494,6 +496,21 @@ trace_init (trace_t * t, const struct sockaddr_in to,
  56. if (protocol)
  57. {
  58. t->icmpfd = socket (PF_INET, SOCK_RAW, protocol->p_proto);
  59. + if (t->icmpfd < 0 && (errno == EPERM || errno == EACCES))
  60. + {
  61. + /* A subprivileged user on GNU/Linux might be allowed
  62. + * to create ICMP packets from a datagram socket.
  63. + * Such packets are always severely crippled.
  64. + */
  65. + errno = 0;
  66. + t->icmpfd = socket (PF_INET, SOCK_DGRAM, protocol->p_proto);
  67. + t->no_ident++;
  68. +
  69. + /* Recover error message for non-Linux systems. */
  70. + if (errno == EPROTONOSUPPORT)
  71. + errno = EPERM;
  72. + }
  73. +
  74. if (t->icmpfd < 0)
  75. error (EXIT_FAILURE, errno, "socket");
  76. @@ -609,7 +626,7 @@ trace_read (trace_t * t, int * type, int * code)
  77. if (ic->icmp_type == ICMP_ECHOREPLY
  78. && (ntohs (ic->icmp_seq) != seqno
  79. - || ntohs (ic->icmp_id) != pid))
  80. + || (ntohs (ic->icmp_id) != pid && t->no_ident == 0)))
  81. return -1;
  82. if (ic->icmp_type == ICMP_TIME_EXCEEDED
  83. @@ -685,6 +702,17 @@ trace_write (trace_t * t)
  84. case TRACE_ICMP:
  85. {
  86. icmphdr_t hdr;
  87. + int i;
  88. +
  89. + /* Deposit deterministic values throughout the header! */
  90. + for (i = 0; i < sizeof (hdr); ++i)
  91. + *((char *) &hdr + i) = i;
  92. +
  93. + /* The subprivileged use case of ICMP sent over datagram
  94. + * sockets needs extra help with identification of target.
  95. + */
  96. + if (t->no_ident)
  97. + *((int *) &hdr + 12 / sizeof(int)) = dest.sin_addr.s_addr;
  98. /* The sequence number is updated to a valid value! */
  99. if (icmp_echo_encode ((unsigned char *) &hdr, sizeof (hdr),
  100. --
  101. 2.26.0.292.g33ef6b2f38