]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Sec 3110] Windows: ntpd DoS by oversized UDP packet
authorJuergen Perlinger <perlinger@ntp.org>
Fri, 9 Sep 2016 16:34:03 +0000 (18:34 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Fri, 9 Sep 2016 16:34:03 +0000 (18:34 +0200)
bk: 57d2e47bYpxCdt81ZHiN7MChYHv19w

ChangeLog
ports/winnt/include/ntp_iocpltypes.h
ports/winnt/ntpd/ntp_iocompletionport.c
ports/winnt/vs2015/ntp.sln

index 0805467dc6b9b1ce7768a039f6a2d87af37546b9..870028d2c53431d33b700a836954605a5ee1b599 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+---
+* [Sec 3110] Windows: ntpd DoS by oversized UDP packet
+  - fixed error handling for truncated UDP packets. <perlinger@ntp.org>
+
 ---
 (4.2.8p8) 2016/06/02 Released by Harlan Stenn <stenn@ntp.org>
 
index 6be5ffc60ed039216df89ed4da964b311b51b292..c2d40acbe4c911f609a518dc4bbc23be306806a1 100644 (file)
@@ -135,6 +135,7 @@ struct IoCtx {
        DevCtx_t *              devCtx;
        DWORD                   errCode;        /* error code of last I/O       */
        DWORD                   byteCount;      /* byte count     "             */
+       DWORD                   ioFlags;        /* in/out flags for recvfrom()  */
        u_int                   flRawMem : 1;   /* buffer is raw memory -> free */
        struct {
                l_fp            DCDSTime;       /* PPS-hack: time of DCD ON     */
index 6512d75488fad971a1c784d2fc5ea4b7b654da4a..4e92717dce7b4267b27e1093e0108ffae4f104c1 100644 (file)
@@ -546,7 +546,7 @@ getEndptFromIoCtx(
        )
 {
        /* Make sure the key matches the context info in the shared
-        * lock, the check for errors. If the error indicates the
+        * lock, then check for errors. If the error indicates the
         * operation was cancelled, let the operation fail silently.
         *
         * !Note! Since we use the lowest bit of the key to distinguish
@@ -554,6 +554,7 @@ getEndptFromIoCtx(
         * LSB is not used in the reverse-link check. Hence we shift
         * it out in both the input key and the registered source.
         */
+       int             oval, olen; /* getsockopt params */
        endpt *         ep    = NULL;
        SharedLock_t *  slock = slAttachShared(ctx->slock);
        if (slock != NULL) {
@@ -576,10 +577,43 @@ getEndptFromIoCtx(
                ep = NULL;
        case ERROR_SUCCESS:             /* all is good */
                break;
+
+       /* [Bug 3019] is hard to squash.
+        * We should not get this, but we do, unfortunately. Obviously
+        * Windows insists in terminating one overlapped I/O request
+        * when it receives a TTL-expired ICMP message, and since the
+        * write that caused it is long finished, this unfortunately
+        * hits the pending receive.
+        *
+        * The only way out seems to be to silently ignore this error
+        * and restart another round, in the hope this condition does
+        * not prevail. Clear any pending socket level errors, too.
+        */
+       case ERROR_HOST_UNREACHABLE:
+               oval = 0;
+               olen = sizeof(oval);
+               getsockopt(ctx->io.sfd, SOL_SOCKET, SO_ERROR, (char*)&oval, &olen);
+               ctx->errCode = ERROR_SUCCESS;
+               break;
+
+       /* [Bug 3110] On POSIX systems, reading UDP data into too small
+        * a buffers silently truncates the message. Under Windows the
+        * data is also truncated, but it blarts loudly about that.
+        * Just pretend all is well, and all will be well.
+        */
+       case ERROR_MORE_DATA:
+       case WSAEMSGSIZE    :
+               ctx->errCode = ERROR_SUCCESS;
+               break;
+
+       /* For any other error, log the error, clear the byt count, but
+        * but return the endpoint. This prevents processing the packet
+        * and keeps the read-chain running -- otherwise NTPD will play
+        * dead duck!
+        */
        default:
-               /* log error, but return -- caller has to handle this! */
                LogIoError(msg, ctx->io.hnd, ctx->errCode);
-               ep = NULL;
+               ctx->byteCount = 0;
                break;
        }
        if (NULL == ep)
@@ -1350,13 +1384,13 @@ QueueSocketRecv(
                "QueueSocketRecv: cannot schedule socket receive";
 
        WSABUF  wsabuf;
-       DWORD   Flags;
        int     rc;
 
        lpo->onIoDone = OnSocketRecv;
        lpo->recv_buf = buff;
        lpo->flRawMem = 0;
-       
+       lpo->ioFlags  = 0;
+
        buff->fd              = lpo->io.sfd;
        buff->recv_srcadr_len = sizeof(buff->recv_srcadr);
        buff->receiver        = receive;
@@ -1365,8 +1399,7 @@ QueueSocketRecv(
        wsabuf.buf = (char *)buff->recv_buffer;
        wsabuf.len = sizeof(buff->recv_buffer);
 
-       Flags = 0;      /* in/out parameter, must be valid! */
-       rc = WSARecvFrom(lpo->io.sfd, &wsabuf, 1, NULL, &Flags,
+       rc = WSARecvFrom(lpo->io.sfd, &wsabuf, 1, NULL, &lpo->ioFlags,
                         &buff->recv_srcadr.sa, &buff->recv_srcadr_len, 
                         &lpo->ol, NULL);
        return !rc || IoResultCheck((DWORD)WSAGetLastError(), lpo, msg);
@@ -1702,10 +1735,16 @@ GetReceivedBuffers(void)
                        break;
 
                case WAIT_FAILED:
+               {
+                       BOOL   dynbuf = FALSE;
+                       char * msgbuf = NTstrerror(GetLastError(), &dynbuf);
                        msyslog(LOG_ERR,
-                               "WaitForMultipleObjects Failed: Error: %m");
+                               "WaitForMultipleObjects Failed: Error: %s", msgbuf);
+                       if (dynbuf)
+                               LocalFree(msgbuf);
                        exit(1);
-                       break;
+               }
+               break;
 
                default:
                        DEBUG_INSIST((index - WAIT_OBJECT_0) <
index c81fe95a3fb91daa7116c4823c15553deac35bac..71d3792d9a537dd844d88142a6325a169b2ef89e 100644 (file)
@@ -1,8 +1,8 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Express 2013 for Windows Desktop
-VisualStudioVersion = 12.0.31101.0
-MinimumVisualStudioVersion = 10.0.40219.1
+# Visual Studio 2015
+VisualStudioVersion = 14.0.24720.00
+MinimumVisualStudioVersion = 12.0.31101.0
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ntpd", "ntpd\ntpd.vcxproj", "{CB61F8BF-9637-495C-9087-E8664B400CE0}"
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "instsrv", "instsrv\instsrv.vcxproj", "{C3534C4D-6DF1-498E-9904-4337878A1515}"