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/

Reply via email to