diff options
Diffstat (limited to 'src/nat/gnunet-service-nat_stun.c')
-rw-r--r-- | src/nat/gnunet-service-nat_stun.c | 178 |
1 files changed, 90 insertions, 88 deletions
diff --git a/src/nat/gnunet-service-nat_stun.c b/src/nat/gnunet-service-nat_stun.c index 639289207..d8b791d0a 100644 --- a/src/nat/gnunet-service-nat_stun.c +++ b/src/nat/gnunet-service-nat_stun.c | |||
@@ -11,12 +11,12 @@ | |||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Affero General Public License for more details. | 13 | Affero General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU Affero General Public License | 15 | You should have received a copy of the GNU Affero General Public License |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | 17 | ||
18 | SPDX-License-Identifier: AGPL3.0-or-later | 18 | SPDX-License-Identifier: AGPL3.0-or-later |
19 | */ | 19 | */ |
20 | /** | 20 | /** |
21 | * This code provides some support for doing STUN transactions. We | 21 | * This code provides some support for doing STUN transactions. We |
22 | * receive the simplest possible packet as the STUN server and try | 22 | * receive the simplest possible packet as the STUN server and try |
@@ -40,15 +40,14 @@ | |||
40 | #include "gnunet_util_lib.h" | 40 | #include "gnunet_util_lib.h" |
41 | #include "nat_stun.h" | 41 | #include "nat_stun.h" |
42 | 42 | ||
43 | #define LOG(kind,...) GNUNET_log_from (kind, "stun", __VA_ARGS__) | 43 | #define LOG(kind, ...) GNUNET_log_from(kind, "stun", __VA_ARGS__) |
44 | 44 | ||
45 | 45 | ||
46 | /** | 46 | /** |
47 | * Context for #stun_get_mapped(). | 47 | * Context for #stun_get_mapped(). |
48 | * Used to store state across processing attributes. | 48 | * Used to store state across processing attributes. |
49 | */ | 49 | */ |
50 | struct StunState | 50 | struct StunState { |
51 | { | ||
52 | uint16_t attr; | 51 | uint16_t attr; |
53 | }; | 52 | }; |
54 | 53 | ||
@@ -65,41 +64,44 @@ struct StunState | |||
65 | * @return #GNUNET_OK if @a arg was initialized | 64 | * @return #GNUNET_OK if @a arg was initialized |
66 | */ | 65 | */ |
67 | static int | 66 | static int |
68 | stun_get_mapped (struct StunState *st, | 67 | stun_get_mapped(struct StunState *st, |
69 | const struct stun_attr *attr, | 68 | const struct stun_attr *attr, |
70 | uint32_t magic, | 69 | uint32_t magic, |
71 | struct sockaddr_in *arg) | 70 | struct sockaddr_in *arg) |
72 | { | 71 | { |
73 | const struct stun_addr *returned_addr; | 72 | const struct stun_addr *returned_addr; |
74 | struct sockaddr_in *sa = (struct sockaddr_in *) arg; | 73 | struct sockaddr_in *sa = (struct sockaddr_in *)arg; |
75 | uint16_t type = ntohs (attr->attr); | 74 | uint16_t type = ntohs(attr->attr); |
76 | 75 | ||
77 | switch (type) | 76 | switch (type) |
78 | { | 77 | { |
79 | case STUN_MAPPED_ADDRESS: | 78 | case STUN_MAPPED_ADDRESS: |
80 | if ( (st->attr == STUN_XOR_MAPPED_ADDRESS) || | 79 | if ((st->attr == STUN_XOR_MAPPED_ADDRESS) || |
81 | (st->attr == STUN_MS_XOR_MAPPED_ADDRESS) ) | 80 | (st->attr == STUN_MS_XOR_MAPPED_ADDRESS)) |
82 | return GNUNET_NO; | 81 | return GNUNET_NO; |
83 | magic = 0; | 82 | magic = 0; |
84 | break; | 83 | break; |
85 | case STUN_MS_XOR_MAPPED_ADDRESS: | 84 | |
86 | if (st->attr == STUN_XOR_MAPPED_ADDRESS) | 85 | case STUN_MS_XOR_MAPPED_ADDRESS: |
86 | if (st->attr == STUN_XOR_MAPPED_ADDRESS) | ||
87 | return GNUNET_NO; | ||
88 | break; | ||
89 | |||
90 | case STUN_XOR_MAPPED_ADDRESS: | ||
91 | break; | ||
92 | |||
93 | default: | ||
87 | return GNUNET_NO; | 94 | return GNUNET_NO; |
88 | break; | 95 | } |
89 | case STUN_XOR_MAPPED_ADDRESS: | 96 | |
90 | break; | 97 | if (ntohs(attr->len) < sizeof(struct stun_addr)) |
91 | default: | ||
92 | return GNUNET_NO; | ||
93 | } | ||
94 | |||
95 | if (ntohs (attr->len) < sizeof (struct stun_addr)) | ||
96 | return GNUNET_NO; | 98 | return GNUNET_NO; |
97 | returned_addr = (const struct stun_addr *)(attr + 1); | 99 | returned_addr = (const struct stun_addr *)(attr + 1); |
98 | if (AF_INET != returned_addr->family) | 100 | if (AF_INET != returned_addr->family) |
99 | return GNUNET_NO; | 101 | return GNUNET_NO; |
100 | st->attr = type; | 102 | st->attr = type; |
101 | sa->sin_family = AF_INET; | 103 | sa->sin_family = AF_INET; |
102 | sa->sin_port = returned_addr->port ^ htons (ntohl(magic) >> 16); | 104 | sa->sin_port = returned_addr->port ^ htons(ntohl(magic) >> 16); |
103 | sa->sin_addr.s_addr = returned_addr->addr ^ magic; | 105 | sa->sin_addr.s_addr = returned_addr->addr ^ magic; |
104 | return GNUNET_OK; | 106 | return GNUNET_OK; |
105 | } | 107 | } |
@@ -119,9 +121,9 @@ stun_get_mapped (struct StunState *st, | |||
119 | * #GNUNET_NO if the packet is invalid (not a stun packet) | 121 | * #GNUNET_NO if the packet is invalid (not a stun packet) |
120 | */ | 122 | */ |
121 | int | 123 | int |
122 | GNUNET_NAT_stun_handle_packet_ (const void *data, | 124 | GNUNET_NAT_stun_handle_packet_(const void *data, |
123 | size_t len, | 125 | size_t len, |
124 | struct sockaddr_in *arg) | 126 | struct sockaddr_in *arg) |
125 | { | 127 | { |
126 | const struct stun_header *hdr; | 128 | const struct stun_header *hdr; |
127 | const struct stun_attr *attr; | 129 | const struct stun_attr *attr; |
@@ -135,76 +137,76 @@ GNUNET_NAT_stun_handle_packet_ (const void *data, | |||
135 | * while 'data' is advanced accordingly. | 137 | * while 'data' is advanced accordingly. |
136 | */ | 138 | */ |
137 | if (len < sizeof(struct stun_header)) | 139 | if (len < sizeof(struct stun_header)) |
138 | { | 140 | { |
139 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 141 | LOG(GNUNET_ERROR_TYPE_DEBUG, |
140 | "Packet too short to be a STUN packet\n"); | 142 | "Packet too short to be a STUN packet\n"); |
141 | return GNUNET_NO; | 143 | return GNUNET_NO; |
142 | } | 144 | } |
143 | hdr = data; | 145 | hdr = data; |
144 | /* Skip header as it is already in hdr */ | 146 | /* Skip header as it is already in hdr */ |
145 | len -= sizeof(struct stun_header); | 147 | len -= sizeof(struct stun_header); |
146 | data += sizeof(struct stun_header); | 148 | data += sizeof(struct stun_header); |
147 | 149 | ||
148 | /* len as advertised in the message */ | 150 | /* len as advertised in the message */ |
149 | advertised_message_size = ntohs (hdr->msglen); | 151 | advertised_message_size = ntohs(hdr->msglen); |
150 | message_magic_cookie = ntohl (hdr->magic); | 152 | message_magic_cookie = ntohl(hdr->magic); |
151 | /* Compare if the cookie match */ | 153 | /* Compare if the cookie match */ |
152 | if (STUN_MAGIC_COOKIE != message_magic_cookie) | 154 | if (STUN_MAGIC_COOKIE != message_magic_cookie) |
153 | { | 155 | { |
154 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 156 | LOG(GNUNET_ERROR_TYPE_DEBUG, |
155 | "Invalid magic cookie for STUN packet\n"); | 157 | "Invalid magic cookie for STUN packet\n"); |
156 | return GNUNET_NO; | 158 | return GNUNET_NO; |
157 | } | 159 | } |
158 | 160 | ||
159 | LOG (GNUNET_ERROR_TYPE_INFO, | 161 | LOG(GNUNET_ERROR_TYPE_INFO, |
160 | "STUN Packet, msg %s (%04x), length: %d\n", | 162 | "STUN Packet, msg %s (%04x), length: %d\n", |
161 | stun_msg2str (ntohs (hdr->msgtype)), | 163 | stun_msg2str(ntohs(hdr->msgtype)), |
162 | ntohs (hdr->msgtype), | 164 | ntohs(hdr->msgtype), |
163 | advertised_message_size); | 165 | advertised_message_size); |
164 | if (advertised_message_size > len) | 166 | if (advertised_message_size > len) |
165 | { | ||
166 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
167 | "Scrambled STUN packet length (got %d, expecting %d)\n", | ||
168 | advertised_message_size, | ||
169 | (int) len); | ||
170 | return GNUNET_NO; | ||
171 | } | ||
172 | len = advertised_message_size; | ||
173 | memset (&st, 0, sizeof(st)); | ||
174 | |||
175 | while (len > 0) | ||
176 | { | ||
177 | if (len < sizeof (struct stun_attr)) | ||
178 | { | 167 | { |
179 | LOG (GNUNET_ERROR_TYPE_INFO, | 168 | LOG(GNUNET_ERROR_TYPE_INFO, |
180 | "Attribute too short (got %d, expecting %d)\n", | 169 | "Scrambled STUN packet length (got %d, expecting %d)\n", |
181 | (int) len, | 170 | advertised_message_size, |
182 | (int) sizeof (struct stun_attr)); | 171 | (int)len); |
183 | break; | 172 | return GNUNET_NO; |
184 | } | 173 | } |
185 | attr = (const struct stun_attr *) data; | 174 | len = advertised_message_size; |
186 | 175 | memset(&st, 0, sizeof(st)); | |
187 | /* compute total attribute length */ | ||
188 | advertised_message_size = ntohs (attr->len) + sizeof (struct stun_attr); | ||
189 | 176 | ||
190 | /* Check if we still have space in our buffer */ | 177 | while (len > 0) |
191 | if (advertised_message_size > len) | ||
192 | { | 178 | { |
193 | LOG (GNUNET_ERROR_TYPE_INFO, | 179 | if (len < sizeof(struct stun_attr)) |
194 | "Inconsistent attribute (length %d exceeds remaining msg len %d)\n", | 180 | { |
195 | advertised_message_size, | 181 | LOG(GNUNET_ERROR_TYPE_INFO, |
196 | (int) len); | 182 | "Attribute too short (got %d, expecting %d)\n", |
197 | break; | 183 | (int)len, |
184 | (int)sizeof(struct stun_attr)); | ||
185 | break; | ||
186 | } | ||
187 | attr = (const struct stun_attr *)data; | ||
188 | |||
189 | /* compute total attribute length */ | ||
190 | advertised_message_size = ntohs(attr->len) + sizeof(struct stun_attr); | ||
191 | |||
192 | /* Check if we still have space in our buffer */ | ||
193 | if (advertised_message_size > len) | ||
194 | { | ||
195 | LOG(GNUNET_ERROR_TYPE_INFO, | ||
196 | "Inconsistent attribute (length %d exceeds remaining msg len %d)\n", | ||
197 | advertised_message_size, | ||
198 | (int)len); | ||
199 | break; | ||
200 | } | ||
201 | if (GNUNET_OK == | ||
202 | stun_get_mapped(&st, | ||
203 | attr, | ||
204 | hdr->magic, | ||
205 | arg)) | ||
206 | ret = GNUNET_OK; | ||
207 | data += advertised_message_size; | ||
208 | len -= advertised_message_size; | ||
198 | } | 209 | } |
199 | if (GNUNET_OK == | ||
200 | stun_get_mapped (&st, | ||
201 | attr, | ||
202 | hdr->magic, | ||
203 | arg)) | ||
204 | ret = GNUNET_OK; | ||
205 | data += advertised_message_size; | ||
206 | len -= advertised_message_size; | ||
207 | } | ||
208 | return ret; | 210 | return ret; |
209 | } | 211 | } |
210 | 212 | ||