-fixes
[oweals/gnunet.git] / src / util / service.c
index ebdf2c61a967c9daba08283a2d1dbe5c83f287f8..7583dccb6d78b6cd59d413f13eca09b46d01eb90 100644 (file)
@@ -106,7 +106,7 @@ parse_ipv4_specification (const char *routeList)
   while (i < count)
   {
     cnt =
-        sscanf (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
+        SSCANF (&routeList[pos], "%u.%u.%u.%u/%u.%u.%u.%u;", &temps[0],
                 &temps[1], &temps[2], &temps[3], &temps[4], &temps[5],
                 &temps[6], &temps[7]);
     if (cnt == 8)
@@ -133,7 +133,7 @@ parse_ipv4_specification (const char *routeList)
     }
     /* try second notation */
     cnt =
-        sscanf (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
+        SSCANF (&routeList[pos], "%u.%u.%u.%u/%u;", &temps[0], &temps[1],
                 &temps[2], &temps[3], &slash);
     if (cnt == 5)
     {
@@ -176,7 +176,7 @@ parse_ipv4_specification (const char *routeList)
     /* try third notation */
     slash = 32;
     cnt =
-        sscanf (&routeList[pos], "%u.%u.%u.%u;", &temps[0], &temps[1],
+        SSCANF (&routeList[pos], "%u.%u.%u.%u;", &temps[0], &temps[1],
                 &temps[2], &temps[3]);
     if (cnt == 4)
     {
@@ -501,14 +501,18 @@ struct GNUNET_SERVICE_Context
   int require_found;
 
   /**
-   * Do we require a matching UID for UNIX domain socket
-   * connections?
+   * Do we require a matching UID for UNIX domain socket connections?
+   * GNUNET_NO means that the UID does not have to match (however,
+   * "match_gid" may still impose other access control checks).
    */
   int match_uid;
 
   /**
-   * Do we require a matching GID for UNIX domain socket
-   * connections?
+   * Do we require a matching GID for UNIX domain socket connections?
+   * Ignored if "match_uid" is GNUNET_YES.  Note that this is about
+   * checking that the client's UID is in our group OR that the
+   * client's GID is our GID.  If both "match_gid" and "match_uid" are
+   * "GNUNET_NO", all users on the local system have access.
    */
   int match_gid;
 
@@ -617,15 +621,50 @@ check_access (void *cls, const struct GNUNET_CONNECTION_Credentials *uc,
 #ifndef WINDOWS
   case AF_UNIX:
     ret = GNUNET_OK;            /* always OK for now */
-    if ((sctx->match_uid == GNUNET_YES) || (sctx->match_gid == GNUNET_YES))
-      ret = GNUNET_NO;
-    if ((uc != NULL) &&
-        ((sctx->match_uid != GNUNET_YES) || (uc->uid == geteuid ()) ||
-         (uc->uid == getuid ())) && ((sctx->match_gid != GNUNET_YES) ||
-                                     (uc->gid == getegid ()) ||
-                                     (uc->gid == getgid ())))
-      ret = GNUNET_YES;
-    else
+    if (sctx->match_uid == GNUNET_YES) 
+    {
+      /* UID match required */
+      ret = (uc != NULL) && (uc->uid == geteuid ());
+    }
+    else if (sctx->match_gid == GNUNET_YES) 
+    {
+      /* group match required */
+      if (uc == NULL) 
+      {
+       /* no credentials, group match not possible */
+       ret = GNUNET_NO;
+      }
+      else
+      {
+       struct group *grp;
+       unsigned int i;
+
+       if (uc->gid != getegid())
+       {
+         /* default group did not match, but maybe the user is in our group, let's check */
+         grp = getgrgid (getegid ());
+         if (NULL == grp)
+         {
+           GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "getgrgid");
+           return GNUNET_NO;
+         }
+         ret = GNUNET_NO;
+         for (i=0; NULL != grp->gr_mem[i]; i++)
+         {
+           struct passwd *nam = getpwnam (grp->gr_mem[i]);
+           if (NULL == nam)
+             continue; /* name in group that is not in user DB !? */
+           if (nam->pw_uid == uc->uid)
+           {
+             /* yes, uid is in our group, allow! */
+             ret = GNUNET_YES;
+             break;
+           }
+         }
+       }
+      }
+    }
+    if (GNUNET_NO == ret)
       LOG (GNUNET_ERROR_TYPE_WARNING, _("Access denied to UID %d / GID %d\n"),
            (uc == NULL) ? -1 : uc->uid, (uc == NULL) ? -1 : uc->gid);
     break;
@@ -1229,9 +1268,9 @@ setup_service (struct GNUNET_SERVICE_Context *sctx)
 #ifndef MINGW
   errno = 0;
   if ((NULL != (lpid = getenv ("LISTEN_PID"))) &&
-      (1 == sscanf (lpid, "%u", &pid)) && (getpid () == (pid_t) pid) &&
+      (1 == SSCANF (lpid, "%u", &pid)) && (getpid () == (pid_t) pid) &&
       (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
-      (1 == sscanf (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
+      (1 == SSCANF (nfds, "%u", &cnt)) && (cnt > 0) && (cnt < FD_SETSIZE) &&
       (cnt + 4 < FD_SETSIZE))
   {
     sctx->lsocks =
@@ -1351,7 +1390,7 @@ write_pid_file (struct GNUNET_SERVICE_Context *sctx, pid_t pid)
   }
   if (0 > FPRINTF (pidfd, "%u", pid))
     LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "fprintf", pif);
-  GNUNET_break (0 == fclose (pidfd));
+  GNUNET_break (0 == FCLOSE (pidfd));
   if ((user != NULL) && (0 < strlen (user)))
     GNUNET_DISK_file_change_owner (pif, user);
   GNUNET_free_non_null (user);