commit afd1610117af1b3e4a669b21d1821b059c75f071
parent 9304dd3be2fde7c9ebc83df00aefa405a6900af9
Author: sin <sin@2f30.org>
Date: Thu, 24 Mar 2016 11:35:32 +0000
add timeout when challenging
a bad client could set the header length to whatever but send
less data. the server would block in read forever.
thanks rain1
Diffstat:
M | stun.c | | | 39 | ++++++++++++++++++++++++++++++--------- |
1 file changed, 30 insertions(+), 9 deletions(-)
diff --git a/stun.c b/stun.c
@@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
+#include <time.h>
#include <unistd.h>
#include <openssl/aes.h>
@@ -40,8 +41,8 @@
#define explicit_bzero bzero
#endif
-#define CHALLENGETIMEO 1000 /* in ms */
-#define RECONNECTTIMEO 60 /* in seconds */
+#define CHALLENGETIMEO 1 /* in seconds */
+#define RECONNECTTIMEO 60 /* in seconds */
#define HDRLEN 2
#define MTU 1440
@@ -420,6 +421,20 @@ readnet(int fd, unsigned char *buf, int len)
}
int
+setrcvtimeo(int netfd, time_t sec)
+{
+ struct timeval tv;
+ int ret;
+
+ tv.tv_sec = sec;
+ tv.tv_usec = 0;
+ ret = setsockopt(netfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+ if (ret < 0)
+ logwarn("failed to set timeout on socket");
+ return ret;
+}
+
+int
challenge(int netfd)
{
unsigned char buf[sizeof(uint32_t)];
@@ -427,29 +442,35 @@ challenge(int netfd)
uint32_t n, reply;
int ret;
+ ret = setrcvtimeo(netfd, CHALLENGETIMEO);
+ if (ret < 0)
+ return -1;
pack32(buf, n = arc4random());
if (writenet(netfd, buf, sizeof(buf)) <= 0)
- return -1;
+ goto err;
pfd[0].fd = netfd;
pfd[0].events = POLLIN;
- ret = poll(pfd, 1, CHALLENGETIMEO);
+ ret = poll(pfd, 1, CHALLENGETIMEO * 1000);
switch (ret) {
case -1:
logwarn("poll failed");
- return -1;
+ goto err;
case 0:
logwarn("challenge-response timed out");
- return -1;
+ goto err;
default:
if (pfd[0].revents & (POLLIN | POLLHUP)) {
if (readnet(netfd, buf, sizeof(buf)) <= 0)
- return -1;
+ goto err;
reply = unpack32(buf);
- if (n + 1 == reply)
+ if (n + 1 == reply) {
+ setrcvtimeo(netfd, 0);
return 0;
- return -1;
+ }
}
}
+err:
+ setrcvtimeo(netfd, 0);
return -1;
}