From d2318c75f62aa96818cfe6294205a54ee7fd31b3 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 12 Feb 2013 13:28:43 +0000 Subject: [PATCH] Unix credentials-passing: add comments explaining how we reach each case --- dbus/dbus-sysdeps-unix.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index a031059..0b518dc 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -1764,6 +1764,14 @@ _dbus_read_credentials_socket (int client_fd, { #ifdef SO_PEERCRED + /* Supported by at least Linux and OpenBSD. + * + * This mechanism passes the process ID and does not require the peer's + * cooperation, so we prefer it over all others. + * + * Notably, on Linux we never use SCM_CREDENTIALS, because this way is + * less fragile. + */ #ifdef __OpenBSD__ struct sockpeercred cr; #else @@ -1783,18 +1791,57 @@ _dbus_read_credentials_socket (int client_fd, cr_len, (int) sizeof (cr), _dbus_strerror (errno)); } #elif defined(HAVE_CMSGCRED) + /* We only check for HAVE_CMSGCRED but we're really assuming that + * the presence of that struct implies SCM_CREDS. Supported by + * at least FreeBSD. + * + * This mechanism requires the peer's cooperation (it has to + * specifically send us a SCM_CREDS message) but it does pass + * the process ID through. + */ struct cmsgcred *cred; cred = (struct cmsgcred *) CMSG_DATA (&cmsg.hdr); pid_read = cred->cmcred_pid; uid_read = cred->cmcred_euid; + + /* ---------------------------------------------------------------- + * When adding new mechanisms, please add a #elif above this point + * if the mechanism supports passing the process ID, or below + * this point if it does not. + * ------------------------------------------------------------- */ + #elif defined(LOCAL_CREDS) + /* On OSs where _dbus_set_local_creds() is needed, setting that option + * requests that the kernel gives us a struct cmsgcred with type SCM_CREDS. + * + * Supported by NetBSD, QNX. Also supported by FreeBSD, but on FreeBSD + * we prefer the version above, because it tells us the process ID. + * + * If I'm reading FreeBSD man pages correctly, (SOL_SOCKET, SCM_CREDS) + * ancillary messages can have either struct cmsgcred or struct sockcred + * as "payload", depending whether it was sent explicitly via SCM_CREDS or + * received implicitly via LOCAL_CREDS... + */ pid_read = DBUS_PID_UNSET; uid_read = cmsg.cred.sc_uid; /* Since we have already got the credentials from this socket, we can * disable its LOCAL_CREDS flag if it was ever set. */ _dbus_set_local_creds (client_fd, FALSE); #elif defined(HAVE_GETPEEREID) + /* getpeereid() originates from D.J. Bernstein and is fairly + * widely-supported: + * + * - AIX? + * - Blackberry? + * - FreeBSD >= 4.6 (but we prefer cmsgcred) + * - Mac OS X + * - Minix >= 3.1.8 + * - MirBSD? + * - OpenBSD >= 3.0 + * - QNX? (but we prefer LOCAL_CREDS for some reason) + * - others? + */ uid_t euid; gid_t egid; if (getpeereid (client_fd, &euid, &egid) == 0) @@ -1806,6 +1853,7 @@ _dbus_read_credentials_socket (int client_fd, _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); } #elif defined(HAVE_GETPEERUCRED) + /* Supported in at least Solaris >= 10. */ ucred_t * ucred = NULL; if (getpeerucred (client_fd, &ucred) == 0) { @@ -1850,6 +1898,19 @@ _dbus_read_credentials_socket (int client_fd, if (ucred != NULL) ucred_free (ucred); #else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ + +#warning Socket credentials not supported on this Unix OS + +/* Please add other operating systems known to support at least one of + * the mechanisms above to this list, keeping alphabetical order. + * Everything else is best-effort. + */ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ + defined(__linux__) || \ + defined(__OpenBSD__) +# error We really ought to support credentials on this OS! +#endif + _dbus_verbose ("Socket credentials not supported on this OS\n"); #endif } -- 1.7.10.4