diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2014-01-06 15:55:35 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2014-01-06 15:55:35 +0000 |
commit | a6bb4b7be996b935ddc6a20d2fa8e5bb2a9e36f5 (patch) | |
tree | 3e8bfed30260d0389dd706de576c59e852cb15c9 | |
parent | 3ca8a53e336a1a829bae93c70fe617af6493201a (diff) | |
download | dbus-a6bb4b7be996b935ddc6a20d2fa8e5bb2a9e36f5.tar.gz |
_dbus_read_credentials_socket: look at all cmsg headers, not just the first
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>
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 28 |
1 files changed, 15 insertions, 13 deletions
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index c12f294e..6fd1b764 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -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 |