Bugzilla bug 106496: fixed the WINNT version of PR_NewTCPSocketPair to NSPRPUB_RELEASE_4_2_BETA1
authorwtc%netscape.com
Fri, 25 Jan 2002 19:16:34 +0000
changeset 2197 48c53093f4925d616b8ab188c4bd5db48da0e53f
parent 2196 08faa7b023a2d23568f6d8e96c3fa928899e3392
child 2198 3af4aee6e8fe4eca1f82429fa9c7dd461b772d4c
child 2199 f3f79419b5f43403083630f61dee6dff43e45400
push idunknown
push userunknown
push dateunknown
bugs106496
Bugzilla bug 106496: fixed the WINNT version of PR_NewTCPSocketPair to verify the source of the connection.
pr/src/io/prsocket.c
--- a/pr/src/io/prsocket.c
+++ b/pr/src/io/prsocket.c
@@ -1380,17 +1380,17 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPa
      * child process.
      *
      * The default implementation below cannot be used for NT
      * because PR_Accept would have associated the I/O completion
      * port with the listening and accepted sockets.
      */
     SOCKET listenSock;
     SOCKET osfd[2];
-    struct sockaddr_in selfAddr;
+    struct sockaddr_in selfAddr, peerAddr;
     int addrLen;
 
     if (!_pr_initialized) _PR_ImplicitInitialization();
 
     osfd[0] = osfd[1] = INVALID_SOCKET;
     listenSock = socket(AF_INET, SOCK_STREAM, 0);
     if (listenSock == INVALID_SOCKET) {
         goto failed;
@@ -1424,20 +1424,34 @@ PR_IMPLEMENT(PRStatus) PR_NewTCPSocketPa
      * This is the behavior of the BSD socket code.  If
      * connect does not return until accept is called, we
      * will need to create another thread to call connect.
      */
     if (connect(osfd[0], (struct sockaddr *) &selfAddr,
             addrLen) == SOCKET_ERROR) {
         goto failed;
     }
-    osfd[1] = accept(listenSock, NULL, NULL);
+    /*
+     * A malicious local process may connect to the listening
+     * socket, so we need to verify that the accepted connection
+     * is made from our own socket osfd[0].
+     */
+    if (getsockname(osfd[0], (struct sockaddr *) &selfAddr,
+            &addrLen) == SOCKET_ERROR) {
+        goto failed;
+    }
+    osfd[1] = accept(listenSock, (struct sockaddr *) &peerAddr, &addrLen);
     if (osfd[1] == INVALID_SOCKET) {
         goto failed;
     }
+    if (peerAddr.sin_port != selfAddr.sin_port) {
+        /* the connection we accepted is not from osfd[0] */
+        PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0);
+        goto failed;
+    }
     closesocket(listenSock);
 
     f[0] = PR_AllocFileDesc(osfd[0], PR_GetTCPMethods());
     if (!f[0]) {
         closesocket(osfd[0]);
         closesocket(osfd[1]);
         /* PR_AllocFileDesc() has invoked PR_SetError(). */
         return PR_FAILURE;