]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
_dbus_read_credentials_socket: look at all cmsg headers, not just the first
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Mon, 6 Jan 2014 15:55:35 +0000 (15:55 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Mon, 6 Jan 2014 15:55:35 +0000 (15:55 +0000)
If there are no cmsg headers, don't fail: this fixes receiving credentials
on TCP sockets under at least GNU/kFreeBSD, and probably FreeBSD too.

If there's more than one cmsg header, ignore any that don't look like
valid SCM_CREDS.

Bug: https://bugs.freedesktop.org/show_bug.cgi?id=69492
Tested-by: Svante Signell
Reviewed-by: Chengwei Yang <chengwei.yang@intel.com>
[added break, altered indentation in response to review -smcv]
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
dbus/dbus-sysdeps-unix.c

index c12f294e2d85d217d4322c6daf60142f82e2f526..6fd1b764b61a162470c77a4ae4806f3ce73e553d 100644 (file)
@@ -1712,16 +1712,6 @@ _dbus_read_credentials_socket  (int              client_fd,
       return FALSE;
     }
 
-#if defined(HAVE_CMSGCRED)
-  if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred))
-                 || cmsg.hdr.cmsg_type != SCM_CREDS)
-    {
-      dbus_set_error (error, DBUS_ERROR_FAILED,
-                      "Message from recvmsg() was not SCM_CREDS");
-      return FALSE;
-    }
-#endif
-
   _dbus_verbose ("read credentials byte\n");
 
   {
@@ -1762,10 +1752,22 @@ _dbus_read_credentials_socket  (int              client_fd,
      * which makes it better than getpeereid().
      */
     struct cmsgcred *cred;
+    struct cmsghdr *cmsgp;
 
-    cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr);
-    pid_read = cred->cmcred_pid;
-    uid_read = cred->cmcred_euid;
+    for (cmsgp = CMSG_FIRSTHDR (&msg);
+         cmsgp != NULL;
+         cmsgp = CMSG_NXTHDR (&msg, cmsgp))
+      {
+        if (cmsgp->cmsg_type == SCM_CREDS &&
+            cmsgp->cmsg_level == SOL_SOCKET &&
+            cmsgp->cmsg_len >= CMSG_LEN (sizeof (struct cmsgcred)))
+          {
+            cred = (struct cmsgcred *) CMSG_DATA (cmsgp);
+            pid_read = cred->cmcred_pid;
+            uid_read = cred->cmcred_euid;
+            break;
+          }
+      }
 
 #elif defined(HAVE_GETPEERUCRED)
     /* Supported in at least Solaris >= 10. It should probably be higher