Index: ChangeLog =================================================================== RCS file: /cvs/dbus/dbus/ChangeLog,v retrieving revision 1.1095 diff -u -p -r1.1095 ChangeLog --- ChangeLog 25 Aug 2006 19:59:49 -0000 1.1095 +++ ChangeLog 28 Aug 2006 13:29:55 -0000 @@ -1,3 +1,9 @@ +2006-08-28 Julio M. Merino Vidal + + * dbus/dbus-sysdeps.c: Add support for LOCAL_CREDS socket + credentials. Fixes "external" authentication under e.g. NetBSD + which does not support any other socket credentials mechanism. + 2006-08-25 John (J5) Palmieri * test/Makefile.am: change find to use syntax that works with non Index: dbus/dbus-sysdeps.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.c,v retrieving revision 1.108 diff -u -p -r1.108 dbus-sysdeps.c --- dbus/dbus-sysdeps.c 18 Aug 2006 15:46:59 -0000 1.108 +++ dbus/dbus-sysdeps.c 28 Aug 2006 13:29:55 -0000 @@ -488,6 +488,35 @@ _dbus_connect_unix_socket (const char } /** + * Enables or disables the reception of credentials on the given socket during + * the next message transmission. This is only effective if the #LOCAL_CREDS + * system feature exists, in which case the other side of the connection does + * not have to do anything special to send the credentials. + * + * @param fd socket on which to change the #LOCAL_CREDS flag. + * @param on whether to enable or disable the #LOCAL_CREDS flag. + */ +static dbus_bool_t +_dbus_set_local_creds (int fd, dbus_bool_t on) +{ + dbus_bool_t retval = TRUE; + +#if defined(LOCAL_CREDS) && !defined(HAVE_CMSGCRED) + int val = on ? 1 : 0; + if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0) + { + _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd); + retval = FALSE; + } + else + _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n", + on ? "enabled" : "disabled", fd); +#endif + + return retval; +} + +/** * Creates a socket and binds it to the given path, * then listens on the socket. The socket is * set to be nonblocking. @@ -605,6 +634,15 @@ _dbus_listen_unix_socket (const char return -1; } + if (!_dbus_set_local_creds (listen_fd, TRUE)) + { + dbus_set_error (error, _dbus_error_from_errno (errno), + "Failed to enable LOCAL_CREDS on socket \"%s\": %s", + path, _dbus_strerror (errno)); + close (listen_fd); + return -1; + } + if (!_dbus_set_fd_nonblocking (listen_fd, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); @@ -875,6 +913,11 @@ _dbus_read_credentials_unix_socket (int struct cmsghdr hdr; struct cmsgcred cred; } cmsg; +#elif defined(LOCAL_CREDS) + struct { + struct cmsghdr hdr; + struct sockcred cred; + } cmsg; #endif _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -889,17 +932,11 @@ _dbus_read_credentials_unix_socket (int _dbus_credentials_clear (credentials); -#if defined(LOCAL_CREDS) && defined(HAVE_CMSGCRED) - /* Set the socket to receive credentials on the next message */ - { - int on = 1; - if (setsockopt (client_fd, 0, LOCAL_CREDS, &on, sizeof (on)) < 0) - { - _dbus_verbose ("Unable to set LOCAL_CREDS socket option\n"); - return FALSE; - } - } -#endif + /* Systems supporting LOCAL_CREDS are configured to have this feature + * enabled (if it does not conflict with HAVE_CMSGCRED) prior accepting + * the connection. Therefore, the received message must carry the + * credentials information without doing anything special. + */ iov.iov_base = &buf; iov.iov_len = 1; @@ -908,7 +945,7 @@ _dbus_read_credentials_unix_socket (int msg.msg_iov = &iov; msg.msg_iovlen = 1; -#ifdef HAVE_CMSGCRED +#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) memset (&cmsg, 0, sizeof (cmsg)); msg.msg_control = &cmsg; msg.msg_controllen = sizeof (cmsg); @@ -933,7 +970,7 @@ _dbus_read_credentials_unix_socket (int return FALSE; } -#ifdef HAVE_CMSGCRED +#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS) if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) { dbus_set_error (error, DBUS_ERROR_FAILED, @@ -965,6 +1002,13 @@ _dbus_read_credentials_unix_socket (int credentials->pid = cmsg.cred.cmcred_pid; credentials->uid = cmsg.cred.cmcred_euid; credentials->gid = cmsg.cred.cmcred_groups[0]; +#elif defined(LOCAL_CREDS) + credentials->pid = DBUS_PID_UNSET; + credentials->uid = cmsg.cred.sc_uid; + credentials->gid = cmsg.cred.sc_gid; + /* 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) uid_t euid; gid_t egid;