On Fri, Apr 16, 2010 at 01:48:17PM +0200, Lars Ellenberg wrote:
> On Fri, Apr 16, 2010 at 01:26:17PM +0200, Lars Marowsky-Bree wrote:
> > On 2010-04-16T11:48:35, Lars Ellenberg <[email protected]> wrote:
> >
> > > We may add the functionality back, in case anyone actually needs it.
> >
> > We need it for ACL support in pacemaker.
I thought that was going to be done differently, as it needs to be
solved differently anyways to support remote TCP (or in general, non
unix domain) connections?
> > I understand that you seem to favor a new connection type value; what
> > would that back-end implementation look like?
>
> This is my proposal for now.
> It keeps backwards ABI compatibility.
>
> Old code works with old and new glue.
> New code works with old and new glue.
>
> New code depending on the new struct members get a define to check for
> at compile time, and a runtime check just as well.
>
> New code depending on the new struct members SHOULD request IPC_UDS_CRED
> instead of IPC_DOMAIN_SOCKET or IPC_ANYTYPE, even though with new glue
> they get the same struct back.
>
> This is so they will notice cleanly when they accidentally are running
> against old glue, and not notice by segfaulting uncontrollably somewhen
> later.
>
> This is still all hackish, but should work well enough.
>
> Makes sense so far?
Ok, the patch posted here was intentionally incomplete,
as it was only meant to show what I was trying to explain above.
But you seem to have misunderstood anyways.
So I'll post it complete
(with a few comment changes, to hopefully clear things up).
It is basically a revert of the revert, moving the members
to the end of the struct, bumping version-info,
and adding the new IPC_UDS_CRED alias.
I hear you don't like this additional ch_type alias.
If I'm the only one liking it, we can sure drop it.
If someone comes up with something better, great.
Note also the version-info bump in
lib/clplumbing/Makefile.am
diff -r d044096fe060 include/clplumbing/ipc.h
--- a/include/clplumbing/ipc.h Thu Apr 15 15:58:50 2010 +0200
+++ b/include/clplumbing/ipc.h Fri Apr 16 22:12:11 2010 +0200
@@ -178,6 +178,18 @@
int conntype;
char failreason[MAXFAILREASON];
+
+ /* New members to support Multi-level ACLs for the CIB,
+ * available since libplumbing.so.2.1.0, added at the
+ * end of the struct to maintain backwards ABI compatibility.
+ *
+ * If you don't like to care for library versions,
+ * create your IPC channels with
+ * c = ipc_wait_conn_constructor(IPC_UDS_CRED, ...),
+ * and these members will be available.
+ */
+ uid_t farside_uid; /* far side uid */
+ gid_t farside_gid; /* far side gid */
};
struct IPC_QUEUE{
@@ -612,8 +624,13 @@
* the pointer to a new waiting connection or NULL if the connection
* can't be created.
* Note:
- * current implementation only supports unix domain socket
- * whose type is IPC_DOMAIN_SOCKET
+ * current implementation supports
+ * IPC_ANYTYPE: alias for IPC_DOMAIN_SOCKET
+ * IPC_DOMAIN_SOCKET: unix domain sockets
+ * IPC_UDS_CRED: an other alias for unix domain sockets,
+ * available since libplumbing.so.2.1.0.
+ * Using it, you can be sure that support for
+ * farside uid + gid credentials is available.
*
*/
extern IPC_WaitConnection * ipc_wait_conn_constructor(const char * ch_type
@@ -637,9 +654,8 @@
* or NULL if the channel can't be created.
*
* Note:
- * current implementation only support unix domain socket
- * whose type is IPC_DOMAIN_SOCKET
- *
+ * See comments for ipc_wait_conn_constructor above
+ * for currently implemented ch_type channel types.
*/
extern IPC_Channel * ipc_channel_constructor(const char * ch_type
, GHashTable* ch_attrs);
@@ -751,6 +767,9 @@
#define IPC_PATH_ATTR "path" /* pathname attribute */
#define IPC_DOMAIN_SOCKET "uds" /* Unix domain socket */
+/* Unix domain socket with farside uid + gid credentials.
+ * Available since libplumbing.so.2.1.0 */
+#define IPC_UDS_CRED "uds_c"
#define IPC_MODE_ATTR "sockmode" /* socket mode attribute */
#ifdef IPC_DOMAIN_SOCKET
diff -r d044096fe060 lib/clplumbing/Makefile.am
--- a/lib/clplumbing/Makefile.am Thu Apr 15 15:58:50 2010 +0200
+++ b/lib/clplumbing/Makefile.am Fri Apr 16 22:12:11 2010 +0200
@@ -63,7 +63,7 @@
libplumb_la_LIBADD = $(top_builddir)/replace/libreplace.la \
$(top_builddir)/lib/pils/libpils.la
-libplumb_la_LDFLAGS = -version-info 2:0:0
+libplumb_la_LDFLAGS = -version-info 3:0:1
libplumbgpl_la_SOURCES = setproctitle.c
libplumbgpl_la_LIBADD = $(top_builddir)/replace/libreplace.la \
diff -r d044096fe060 lib/clplumbing/ipcsocket.c
--- a/lib/clplumbing/ipcsocket.c Thu Apr 15 15:58:50 2010 +0200
+++ b/lib/clplumbing/ipcsocket.c Fri Apr 16 22:12:11 2010 +0200
@@ -2204,6 +2204,8 @@
temp_ch->low_flow_mark = -1;
temp_ch->conntype = conntype;
temp_ch->refcount = 0;
+ temp_ch->farside_uid = -1;
+ temp_ch->farside_gid = -1;
return temp_ch;
@@ -2341,14 +2343,20 @@
}
if (auth_info == NULL
|| (auth_info->uid == NULL && auth_info->gid == NULL)) {
- return IPC_OK; /* no restriction for authentication */
+ ret = IPC_OK; /* no restriction for authentication */
}
/* Get the credential information for our peer */
conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;
if (getsockopt(conn_info->s, SOL_SOCKET, SO_PEERCRED, &cred, &n) != 0
|| (size_t)n != sizeof(cred)) {
- return IPC_FAIL;
+ return ret;
+ }
+
+ ch->farside_uid = cred.uid;
+ ch->farside_gid = cred.gid;
+ if (ret == IPC_OK) {
+ return ret;
}
#if 0
cl_log(LOG_DEBUG, "SO_PEERCRED returned [%d, (%ld:%ld)]"
@@ -2419,13 +2427,19 @@
if (auth_info == NULL
|| (auth_info->uid == NULL && auth_info->gid == NULL)) {
- return IPC_OK; /* no restriction for authentication */
+ ret = IPC_OK; /* no restriction for authentication */
}
conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;
if (getpeereid(conn_info->s, &euid, &egid) < 0) {
cl_perror("getpeereid() failure");
- return IPC_FAIL;
+ return ret;
+ }
+
+ ch->farside_uid = euid;
+ ch->farside_gid = egid;
+ if (ret == IPC_OK) {
+ return ret;
}
/* Check credentials against authorization information */
@@ -2524,7 +2538,7 @@
#endif
struct SOCKET_CH_PRIVATE *conn_info;
- int ret = IPC_OK;
+ int ret = IPC_FAIL;
char buf;
/* Compute size without padding */
@@ -2543,7 +2557,7 @@
if (auth_info == NULL
|| (auth_info->uid == NULL && auth_info->gid == NULL)) {
- return IPC_OK; /* no restriction for authentication */
+ ret = IPC_OK; /* no restriction for authentication */
}
conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;
@@ -2566,12 +2580,19 @@
|| cmsg->cmsg_len < CMSGSIZE
|| cmsg->cmsg_type != SCM_CREDS) {
cl_perror("can't get credential information from peer");
- return IPC_FAIL;
+ return ret;
}
/* Avoid alignment issues - just copy it! */
memcpy(&cred, CMSG_DATA(cmsg), sizeof(cred));
+ ch->farside_uid = cred.crEuid;
+ ch->farside_gid = cred.crEgid;
+ if (ret == IPC_OK) {
+ return ret;
+ }
+
+ ret = IPC_OK;
if ( auth_info->uid
&& g_hash_table_lookup(auth_info->uid, &(cred.crEuid)) == NULL) {
@@ -2618,7 +2639,7 @@
socket_verify_auth(struct IPC_CHANNEL* ch, struct IPC_AUTH * auth_info)
{
int len = 0;
- int ret = IPC_OK;
+ int ret = IPC_FAIL;
struct stat stat_buf;
struct sockaddr_un *peer_addr = NULL;
struct SOCKET_CH_PRIVATE *ch_private = NULL;
@@ -2636,26 +2657,36 @@
} else if (auth_info == NULL
|| (auth_info->uid == NULL && auth_info->gid == NULL)) {
- return IPC_OK; /* no restriction for authentication */
+ ret = IPC_OK; /* no restriction for authentication */
- } else if(ch_private == NULL) {
+ }
+
+ if(ch_private == NULL) {
cl_log(LOG_ERR, "No channel private data available");
- return IPC_FAIL;
+ return ret;
} else if(peer_addr == NULL) {
cl_log(LOG_ERR, "No peer information available");
- return IPC_FAIL;
+ return ret;
}
len = SUN_LEN(peer_addr);
if(len < 1) {
cl_log(LOG_ERR, "No peer information available");
- return IPC_FAIL;
+ return ret;
}
peer_addr->sun_path[len] = 0;
stat(peer_addr->sun_path, &stat_buf);
+ ch->farside_uid = stat_buf.st_uid;
+ ch->farside_gid = stat_buf.st_gid;
+ if (ret == IPC_OK) {
+ return ret;
+ }
+
+ ret = IPC_OK;
+
if ((auth_info->uid == NULL || g_hash_table_size(auth_info->uid) == 0)
&& auth_info->gid != NULL
&& g_hash_table_size(auth_info->gid) != 0) {
@@ -2704,6 +2735,9 @@
conn_info = (struct SOCKET_CH_PRIVATE *) ch->ch_private;
+ ch->farside_uid = conn_info->farside_uid;
+ ch->farside_gid = conn_info->farside_gid;
+
if (auth_info == NULL
|| (auth_info->uid == NULL && auth_info->gid == NULL)) {
return IPC_OK; /* no restriction for authentication */
@@ -2751,12 +2785,18 @@
if (auth_info == NULL
|| (auth_info->uid == NULL && auth_info->gid == NULL)) {
- return IPC_OK; /* no restriction for authentication */
+ rc = IPC_OK; /* no restriction for authentication */
}
if (getpeerucred(conn_info->s, &ucred) < 0) {
cl_perror("getpeereid() failure");
- return IPC_FAIL;
+ return rc;
+ }
+
+ ch->farside_uid = ucred_geteuid(ucred);
+ ch->farside_gid = ucred_getegid(ucred);
+ if (rc == IPC_OK) {
+ return rc;
}
/* Check credentials against authorization information */
diff -r d044096fe060 lib/clplumbing/ocf_ipc.c
--- a/lib/clplumbing/ocf_ipc.c Thu Apr 15 15:58:50 2010 +0200
+++ b/lib/clplumbing/ocf_ipc.c Fri Apr 16 22:12:11 2010 +0200
@@ -62,6 +62,7 @@
ipc_wait_conn_constructor(const char * ch_type, GHashTable* ch_attrs)
{
if (strcmp(ch_type, "domain_socket") == 0
+ || strcmp(ch_type, IPC_UDS_CRED) == 0
|| strcmp(ch_type, IPC_ANYTYPE) == 0
|| strcmp(ch_type, IPC_DOMAIN_SOCKET) == 0) {
return socket_wait_conn_new(ch_attrs);
@@ -73,6 +74,7 @@
ipc_channel_constructor(const char * ch_type, GHashTable* ch_attrs)
{
if (strcmp(ch_type, "domain_socket") == 0
+ || strcmp(ch_type, IPC_UDS_CRED) == 0
|| strcmp(ch_type, IPC_ANYTYPE) == 0
|| strcmp(ch_type, IPC_DOMAIN_SOCKET) == 0) {
--
: Lars Ellenberg
: LINBIT | Your Way to High Availability
: DRBD/HA support and consulting http://www.linbit.com
DRBD® and LINBIT® are registered trademarks of LINBIT, Austria.
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/