]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Normalize the permission checking code, and check permissions in more places.
authormike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sat, 16 Apr 2011 01:25:40 +0000 (01:25 +0000)
committermike <mike@7a7537e8-13f0-0310-91df-b6672ffda945>
Sat, 16 Apr 2011 01:25:40 +0000 (01:25 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@9692 7a7537e8-13f0-0310-91df-b6672ffda945

backend/usb-darwin.c
scheduler/conf.h
scheduler/cups-deviced.c
scheduler/cups-driverd.cxx
scheduler/printers.c
scheduler/process.c
scheduler/util.c
scheduler/util.h

index 3d6f113a4a8996b64c53e007fef9e0bca6688a8c..dd334a20760ee037d1049a18b2367c6d81b11f4d 100644 (file)
@@ -1428,28 +1428,21 @@ static kern_return_t load_classdriver(CFStringRef           driverPath,
       return (kr);
   }
   else if (bundleinfo.st_uid ||
-           (bundleinfo.st_gid && (bundleinfo.st_mode & S_IWGRP)) ||
+           (bundleinfo.st_gid && bundleinfo.st_gid != 80 &&
+           (bundleinfo.st_mode & S_IWGRP)) ||
+          (bundleinfo.st_mode & S_ISUID) ||
           (bundleinfo.st_mode & S_IWOTH))
   {
     fprintf(stderr, "DEBUG: Class driver \"%s\" has insecure file "
                    "permissions (0%o/uid=%d/gid=%d).\n", bundlestr,
                    bundleinfo.st_mode, (int)bundleinfo.st_uid,
                    (int)bundleinfo.st_gid);
-    if (bundleinfo.st_uid ||
-       (bundleinfo.st_gid && bundleinfo.st_gid != 80 &&
-        (bundleinfo.st_mode & S_IWGRP)) ||
-       (bundleinfo.st_mode & (S_ISUID | S_IWOTH)))
-      fputs("STATE: +cups-insecure-filter-warning\n", stderr);
-
-    if (bundleinfo.st_uid ||
-        (bundleinfo.st_gid && bundleinfo.st_gid != 80 &&
-        (bundleinfo.st_mode & S_IWOTH)))
-    {
-      if (driverPath)
-        return (load_classdriver(NULL, intf, printerDriver));
-      else
-        return (kr);
-    }
+    fputs("STATE: +cups-insecure-filter-warning\n", stderr);
+
+    if (driverPath)
+      return (load_classdriver(NULL, intf, printerDriver));
+    else
+      return (kr);
   }
 
  /*
index c3479e17208d3af38aa400c673a4aaf8a61da864..e4725ff82a8bb6278c42e09313cc974b1f522de1 100644 (file)
@@ -268,6 +268,7 @@ extern int  cupsdCheckPermissions(const char *filename,
                                      const char *suffix, int mode,
                                      int user, int group, int is_dir,
                                      int create_dir);
+extern int     cupsdCheckProgram(const char *filename, cupsd_printer_t *p);
 extern void    cupsdFreeAliases(cups_array_t *aliases);
 extern char    *cupsdGetDateTime(struct timeval *t, cupsd_time_t format);
 #ifdef HAVE_GSSAPI
index 62bf20801db7907a9edbf3a88150df47bdb31da6..f2d99c8a71a6dd8ce30cb2e156c93c9fd67c3092 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Device scanning mini-daemon for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -767,6 +767,9 @@ start_backend(const char *name,             /* I - Backend to run */
 
   snprintf(program, sizeof(program), "%s/backend/%s", server_bin, name);
 
+  if (!cupsdCheckProgram(program))
+    return (-1);
+
   backend = backends + num_backends;
 
   argv[0] = (char *)name;
index 8f78df3b865f066a8e0653c3ffead2f82d103925..58ceb8c369c174202875e86e231868cd930260ff 100644 (file)
@@ -1606,9 +1606,13 @@ load_drivers(cups_array_t *include,      /* I - Drivers to include */
     * Run the driver with no arguments and collect the output...
     */
 
-    argv[0] = dent->filename;
     snprintf(filename, sizeof(filename), "%s/%s", drivers, dent->filename);
 
+    if (!cupsdCheckProgram(filename))
+      continue;
+
+    argv[0] = dent->filename;
+
     if ((fp = cupsdPipeCommand(&pid, filename, argv, 0)) != NULL)
     {
       while (cupsFileGets(fp, line, sizeof(line)))
index 8d9a7f78b2c1e49b4023b8a54640b2e4267e1ca0..f705bf3bb6795f24391d2879698832a2c11332de 100644 (file)
@@ -3563,9 +3563,8 @@ add_printer_filter(
   size_t       maxsize = 0;            /* Maximum supported file size */
   mime_type_t  *temptype,              /* MIME type looping var */
                *desttype;              /* Destination MIME type */
-  char         filename[1024],         /* Full filter filename */
-               *dirsep;                /* Pointer to directory separator */
-  struct stat  fileinfo;               /* File information */
+  mime_filter_t        *filterptr;             /* MIME filter */
+  char         filename[1024];         /* Full filter filename */
 
 
   cupsdLogMessage(CUPSD_LOG_DEBUG2,
@@ -3633,8 +3632,7 @@ add_printer_filter(
   }
 
  /*
-  * See if the filter program exists; if not, stop the printer and flag
-  * the error!
+  * Check permissions on the filter and its containing directory...
   */
 
   if (strcmp(program, "-"))
@@ -3644,74 +3642,7 @@ add_printer_filter(
     else
       snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program);
 
-    if (stat(filename, &fileinfo))
-    {
-      memset(&fileinfo, 0, sizeof(fileinfo));
-
-      snprintf(p->state_message, sizeof(p->state_message),
-               "Printer driver \"%s\" not available: %s", filename,
-              strerror(errno));
-      cupsdSetPrinterReasons(p, "+cups-missing-filter-warning");
-
-      cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message);
-    }
-
-   /*
-    * When running as root, do additional security checks...
-    */
-
-    else if (!RunUser)
-    {
-     /*
-      * Only use filters that are owned by root and do not have world write
-      * permissions.
-      */
-
-      if (fileinfo.st_uid ||
-          (fileinfo.st_gid && (fileinfo.st_mode & S_IWGRP)) ||
-          (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0)
-      {
-       snprintf(p->state_message, sizeof(p->state_message),
-                "Printer driver \"%s\" has insecure permissions "
-                "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode,
-                (int)fileinfo.st_uid, (int)fileinfo.st_gid);
-
-#ifdef __APPLE__ /* Don't flag filters with group write for "admin" */
-        if (fileinfo.st_uid ||
-           (fileinfo.st_gid && fileinfo.st_gid != 80 &&
-            (fileinfo.st_mode & S_IWGRP)) ||
-           (fileinfo.st_mode & (S_ISUID | S_IWOTH)))
-#endif /* __APPLE__ */
-       cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning");
-
-       cupsdLogMessage(CUPSD_LOG_WARN, "%s: %s", p->name, p->state_message);
-      }
-      else if (fileinfo.st_mode)
-      {
-       /*
-       * Similarly, check that the parent directory is also owned by root and
-       * does not have world write permissions.
-       */
-
-       if ((dirsep = strrchr(filename, '/')) != NULL)
-         *dirsep = '\0';
-
-       if (!stat(filename, &fileinfo) &&
-           (fileinfo.st_uid ||
-            (fileinfo.st_gid && (fileinfo.st_mode & S_IWGRP)) ||
-            (fileinfo.st_mode & (S_ISUID | S_IWOTH)) != 0))
-       {
-         snprintf(p->state_message, sizeof(p->state_message),
-                  "Printer driver directory \"%s\" has insecure permissions "
-                  "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode,
-                  (int)fileinfo.st_uid, (int)fileinfo.st_gid);
-
-         cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning");
-
-         cupsdLogMessage(CUPSD_LOG_WARN, "%s: %s", p->name, p->state_message);
-       }
-      }
-    }
+    cupsdCheckProgram(filename, p);
   }
 
  /*
@@ -3732,7 +3663,8 @@ add_printer_filter(
                        "%s", p->name, temptype->super, temptype->type,
                        desttype->super, desttype->type,
                        cost, program);
-        mimeAddFilter(MimeDatabase, temptype, desttype, cost, program);
+        filterptr = mimeAddFilter(MimeDatabase, temptype, desttype, cost,
+                                 program);
 
         if (!mimeFilterLookup(MimeDatabase, desttype, filtertype))
         {
@@ -3750,8 +3682,12 @@ add_printer_filter(
                        "%s", p->name, temptype->super, temptype->type,
                        filtertype->super, filtertype->type,
                        cost, program);
-        mimeAddFilter(MimeDatabase, temptype, filtertype, cost, program);
+        filterptr = mimeAddFilter(MimeDatabase, temptype, filtertype, cost,
+                                 program);
       }
+
+      if (filterptr)
+       filterptr->maxsize = maxsize;
     }
 }
 
index 0bd534639b9a882e6a43d39b9af53a9370758441..4063dac37fe13cbb4353e76aa385232491a81d12 100644 (file)
@@ -14,6 +14,8 @@
  *
  * Contents:
  *
+ *   cupsdCheckProgram()   - Check the permissions of the given program and its
+ *                           containing directory.
  *   cupsdCreateProfile()  - Create an execution profile for a subprocess.
  *   cupsdDestroyProfile() - Delete an execution profile.
  *   cupsdEndProcess()     - End a process.
@@ -63,6 +65,201 @@ static char *cupsd_requote(char *dst, const char *src, size_t dstsize);
 #endif /* HAVE_SANDBOX_H */
 
 
+/*
+ * 'cupsdCheckProgram()' - Check the permissions of the given program and its
+ *                         containing directory.
+ */
+
+int                                    /* O - 1 if OK, 0 if not OK */
+cupsdCheckProgram(
+    const char      *filename,         /* I - Filename to check */
+    cupsd_printer_t *p)                        /* I - Printer, if any */
+{
+  struct stat          fileinfo;       /* File information */
+  char                 temp[1024],     /* Parent directory filename */
+                       *ptr;           /* Pointer into parent directory */
+
+
+ /*
+  * Does the program even exist and is it accessible?
+  */
+
+  if (stat(filename, &fileinfo))
+  {
+   /*
+    * Nope...
+    */
+
+    if (p)
+    {
+      snprintf(p->state_message, sizeof(p->state_message),
+               "Printer driver \"%s\" not available: %s", filename,
+              strerror(errno));
+      cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message);
+
+      if (cupsdSetPrinterReasons(p, "+cups-missing-filter-warning"))
+       cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL,
+                     "Printer driver \"%s\" not available.", filename);
+    }
+    else
+      cupsdLogMessage(CUPSD_LOG_ERROR, "Program \"%s\" not available: %s",
+                     filename, strerror(errno));
+
+    return (0);
+  }
+
+ /*
+  * Are we running as root?
+  */
+
+  if (RunUser)
+  {
+   /*
+    * Nope, so anything goes...
+    */
+
+    return (1);
+  }
+
+ /*
+  * Verify permission of the program itself:
+  *
+  * 1. Must be owned by root
+  * 2. Must not be writable by group unless group is root/wheel/admin
+  * 3. Must not be setuid
+  * 4. Must not be writable by others
+  */
+
+  if (fileinfo.st_uid ||               /* 1. Must be owned by root */
+#ifdef __APPLE__
+      ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid &&
+       fileinfo.st_gid != 80) ||       /* 2. Must not be writable by group */
+#else
+      ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid) ||
+                                       /* 2. Must not be writable by group */
+#endif /* __APPLE__ */
+      (fileinfo.st_mode & S_ISUID) ||  /* 3. Must not be setuid */
+      (fileinfo.st_mode & S_IWOTH))    /* 4. Must not be writable by others */
+  {
+    if (p)
+    {
+      snprintf(p->state_message, sizeof(p->state_message),
+               "Printer driver \"%s\" has insecure permissions "
+              "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode,
+              (int)fileinfo.st_uid, (int)fileinfo.st_gid);
+
+      cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message);
+                    
+      if (cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"))
+       cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL, "%s",
+                     p->state_message);
+    }
+    else
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "Program \"%s\" has insecure permissions "
+                     "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode,
+                     (int)fileinfo.st_uid, (int)fileinfo.st_gid);
+
+    errno = EPERM;
+
+    return (0);
+  }
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                 "%s%s \"%s\" permissions OK "
+                 "(0%o/uid=%d/gid=%d).", p ? p->name : "",
+                 p ? ": Printer driver" : "Program", filename,
+                 fileinfo.st_mode, (int)fileinfo.st_uid,
+                 (int)fileinfo.st_gid);
+
+ /*
+  * Now check the containing directory...
+  */
+
+  strlcpy(temp, filename, sizeof(temp));
+  if ((ptr = strrchr(temp, '/')) != NULL)
+  {
+    if (ptr == temp)
+      ptr[1] = '\0';
+    else
+      *ptr = '\0';
+  }
+
+  if (stat(temp, &fileinfo))
+  {
+   /*
+    * Doesn't exist...
+    */
+
+    if (p)
+    {
+      snprintf(p->state_message, sizeof(p->state_message),
+               "Printer driver directory \"%s\" not available: %s", temp,
+              strerror(errno));
+      cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message);
+
+      if (cupsdSetPrinterReasons(p, "+cups-missing-filter-warning"))
+       cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL,
+                     "Printer driver directory \"%s\" not available.", temp);
+    }
+    else
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                      "Program directory \"%s\" not available: %s", temp,
+                     strerror(errno));
+
+    return (0);
+  }
+
+  if (fileinfo.st_uid ||               /* 1. Must be owned by root */
+#ifdef __APPLE__
+      ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid &&
+       fileinfo.st_gid != 80) ||       /* 2. Must not be writable by group */
+#else
+      ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid) ||
+                                       /* 2. Must not be writable by group */
+#endif /* __APPLE__ */
+      (fileinfo.st_mode & S_ISUID) ||  /* 3. Must not be setuid */
+      (fileinfo.st_mode & S_IWOTH))    /* 4. Must not be writable by others */
+  {
+    if (p)
+    {
+      snprintf(p->state_message, sizeof(p->state_message),
+              "Printer driver directory \"%s\" has insecure permissions "
+              "(0%o/uid=%d/gid=%d).", temp, fileinfo.st_mode,
+              (int)fileinfo.st_uid, (int)fileinfo.st_gid);
+
+      cupsdLogMessage(CUPSD_LOG_ERROR, "%s: %s", p->name, p->state_message);
+
+      if (cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"))
+       cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL, "%s",
+                     p->state_message);
+    }
+    else
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "Program directory \"%s\" has insecure permissions "
+                     "(0%o/uid=%d/gid=%d).", temp, fileinfo.st_mode,
+                     (int)fileinfo.st_uid, (int)fileinfo.st_gid);
+
+    errno = EPERM;
+
+    return (0);
+  }
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                 "%s%s directory \"%s\" permissions OK "
+                 "(0%o/uid=%d/gid=%d).", p ? p->name : "",
+                 p ? ": Printer driver" : "Program", temp,
+                 fileinfo.st_mode, (int)fileinfo.st_uid,
+                 (int)fileinfo.st_gid);
+
+ /*
+  * If we get here then we can "safely" run this program...
+  */
+
+  return (1);
+}
+
+
 /*
  * 'cupsdCreateProfile()' - Create an execution profile for a subprocess.
  */
@@ -317,7 +514,6 @@ cupsdStartProcess(
   char         *real_argv[103],        /* Real command-line arguments */
                cups_exec[1024];        /* Path to "cups-exec" program */
   int          user;                   /* Command UID */
-  struct stat  commandinfo;            /* Command file information */
   cupsd_proc_t *proc;                  /* New process record */
 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
   struct sigaction action;             /* POSIX signal handler */
@@ -329,6 +525,8 @@ cupsdStartProcess(
 #endif /* __APPLE__ */
 
 
+  *pid = 0;
+
  /*
   * Figure out the UID for the child process...
   */
@@ -344,110 +542,8 @@ cupsdStartProcess(
   * Check the permissions of the command we are running...
   */
 
-  if (stat(command, &commandinfo))
-  {
-    *pid = 0;
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                   "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
-                   "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
-                   "profile=%p, job=%p(%d), pid=%p) = %d",
-                   command, argv, envp, infd, outfd, errfd, backfd, sidefd,
-                   root, profile, job, job ? job->id : 0, pid, *pid);
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "%s%s \"%s\" not available: %s",
-                   job && job->printer ? job->printer->name : "",
-                   job && job->printer ? ": Printer driver" : "Program",
-                   command, strerror(errno));
-
-    if (job && job->printer)
-    {
-      if (cupsdSetPrinterReasons(job->printer, "+cups-missing-filter-warning"))
-       cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL,
-                     "Printer driver \"%s\" not available.", command);
-    }
-
-    return (0);
-  }
-  else if (!RunUser &&
-           ((commandinfo.st_mode & (S_ISUID | S_IWOTH)) ||
-            commandinfo.st_uid))
-  {
-    *pid = 0;
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                   "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
-                   "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
-                   "profile=%p, job=%p(%d), pid=%p) = %d",
-                   command, argv, envp, infd, outfd, errfd, backfd, sidefd,
-                   root, profile, job, job ? job->id : 0, pid, *pid);
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "%s%s \"%s\" has insecure permissions "
-                   "(0%o/uid=%d/gid=%d).",
-                   job && job->printer ? job->printer->name : "",
-                   job && job->printer ? ": Printer driver" : "Program",
-                   command, commandinfo.st_mode,
-                   (int)commandinfo.st_uid, (int)commandinfo.st_gid);
-
-    if (job && job->printer)
-    {
-      if (cupsdSetPrinterReasons(job->printer, "+cups-insecure-filter-warning"))
-       cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL,
-                     "Printer driver \"%s\" has insecure permissions "
-                     "(0%o/uid=%d/gid=%d).", command, commandinfo.st_mode,
-                     (int)commandinfo.st_uid, (int)commandinfo.st_gid);
-    }
-
-    errno = EPERM;
-
-    return (0);
-  }
-  else if ((commandinfo.st_uid != user || !(commandinfo.st_mode & S_IXUSR)) &&
-           (commandinfo.st_gid != Group || !(commandinfo.st_mode & S_IXGRP)) &&
-           !(commandinfo.st_mode & S_IXOTH))
-  {
-    *pid = 0;
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                   "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
-                   "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
-                   "profile=%p, job=%p(%d), pid=%p) = %d",
-                   command, argv, envp, infd, outfd, errfd, backfd, sidefd,
-                   root, profile, job, job ? job->id : 0, pid, *pid);
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "%s%s \"%s\" does not have execute permissions "
-                   "(0%o/uid=%d/gid=%d).",
-                   job && job->printer ? job->printer->name : "",
-                   job && job->printer ? ": Printer driver" : "Program",
-                   command, commandinfo.st_mode, (int)commandinfo.st_uid,
-                   (int)commandinfo.st_gid);
-
-    errno = EPERM;
+  if (!cupsdCheckProgram(command, job ? job->printer : NULL))
     return (0);
-  }
-  else if (!RunUser && commandinfo.st_gid && (commandinfo.st_mode & S_IWGRP))
-  {
-    cupsdLogMessage(CUPSD_LOG_WARN,
-                    "%s%s \"%s\" has insecure permissions "
-                   "(0%o/uid=%d/gid=%d).",
-                   job && job->printer ? job->printer->name : "",
-                   job && job->printer ? ": Printer driver" : "Program",
-                   command, commandinfo.st_mode,
-                   (int)commandinfo.st_uid, (int)commandinfo.st_gid);
-
-#ifdef __APPLE__ /* Don't flag filters with group write for "admin" */
-    if (commandinfo.st_gid != 80 && job && job->printer)
-#else
-    if (job && job->printer)
-#endif /* __APPLE__ */
-    {
-      if (cupsdSetPrinterReasons(job->printer, "+cups-insecure-filter-warning"))
-       cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL,
-                     "Printer driver \"%s\" has insecure permissions "
-                     "(0%o/uid=%d/gid=%d).", command, commandinfo.st_mode,
-                     (int)commandinfo.st_uid, (int)commandinfo.st_gid);
-    }
-  }
 
 #if defined(__APPLE__)
   if (envp)
index c0006efa8b218dd8655365030f630a9dbbf79623..ee3404f513b4b3ce3e4ecd43e2d54cfffc46222d 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Mini-daemon utility functions for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -14,6 +14,8 @@
  *
  * Contents:
  *
+ *   cupsdCheckProgram()       - Check the permissions of the given program and
+ *                               its containing directory.
  *   cupsdCompareNames()       - Compare two names.
  *   cupsdCreateStringsArray() - Create a CUPS array of strings.
  *   cupsdExec()               - Run a program with the correct environment.
@@ -39,6 +41,145 @@ extern char **environ;
 #endif /* __APPLE__ */ 
 
 
+/*
+ * 'cupsdCheckProgram()' - Check the permissions of the given program and its
+ *                         containing directory.
+ *
+ * Note: This function is a parallel implementation of the scheduler function
+ *       of the same name.
+ */
+
+int                                    /* O - 1 if OK, 0 if not OK */
+cupsdCheckProgram(
+    const char      *filename)         /* I - Filename to check */
+{
+  struct stat          fileinfo;       /* File information */
+  char                 temp[1024],     /* Parent directory filename */
+                       *ptr;           /* Pointer into parent directory */
+
+
+ /*
+  * Does the program even exist and is it accessible?
+  */
+
+  if (stat(filename, &fileinfo))
+  {
+   /*
+    * Nope...
+    */
+
+    fprintf(stderr, "ERROR: Program \"%s\" not available: %s", filename,
+            strerror(errno));
+
+    return (0);
+  }
+
+ /*
+  * Are we running as root?
+  */
+
+  if (geteuid())
+  {
+   /*
+    * Nope, so anything goes...
+    */
+
+    return (1);
+  }
+
+ /*
+  * Verify permission of the program itself:
+  *
+  * 1. Must be owned by root
+  * 2. Must not be writable by group unless group is root/wheel/admin
+  * 3. Must not be setuid
+  * 4. Must not be writable by others
+  */
+
+  if (fileinfo.st_uid ||               /* 1. Must be owned by root */
+#ifdef __APPLE__
+      ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid &&
+       fileinfo.st_gid != 80) ||       /* 2. Must not be writable by group */
+#else
+      ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid) ||
+                                       /* 2. Must not be writable by group */
+#endif /* __APPLE__ */
+      (fileinfo.st_mode & S_ISUID) ||  /* 3. Must not be setuid */
+      (fileinfo.st_mode & S_IWOTH))    /* 4. Must not be writable by others */
+  {
+    fprintf(stderr,
+            "ERROR: Program \"%s\" has insecure permissions "
+           "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode,
+           (int)fileinfo.st_uid, (int)fileinfo.st_gid);
+
+    errno = EPERM;
+
+    return (0);
+  }
+
+  fprintf(stderr, "DEBUG2: Program \"%s\" permissions OK (0%o/uid=%d/gid=%d).",
+          filename, fileinfo.st_mode, (int)fileinfo.st_uid,
+         (int)fileinfo.st_gid);
+
+ /*
+  * Now check the containing directory...
+  */
+
+  strlcpy(temp, filename, sizeof(temp));
+  if ((ptr = strrchr(temp, '/')) != NULL)
+  {
+    if (ptr == temp)
+      ptr[1] = '\0';
+    else
+      *ptr = '\0';
+  }
+
+  if (stat(temp, &fileinfo))
+  {
+   /*
+    * Doesn't exist...
+    */
+
+    fprintf(stderr, "ERROR: Program directory \"%s\" not available: %s", temp,
+           strerror(errno));
+
+    return (0);
+  }
+
+  if (fileinfo.st_uid ||               /* 1. Must be owned by root */
+#ifdef __APPLE__
+      ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid &&
+       fileinfo.st_gid != 80) ||       /* 2. Must not be writable by group */
+#else
+      ((fileinfo.st_mode & S_IWGRP) && fileinfo.st_gid) ||
+                                       /* 2. Must not be writable by group */
+#endif /* __APPLE__ */
+      (fileinfo.st_mode & S_ISUID) ||  /* 3. Must not be setuid */
+      (fileinfo.st_mode & S_IWOTH))    /* 4. Must not be writable by others */
+  {
+    fprintf(stderr,
+            "ERROR: Program directory \"%s\" has insecure permissions "
+           "(0%o/uid=%d/gid=%d).", temp, fileinfo.st_mode,
+           (int)fileinfo.st_uid, (int)fileinfo.st_gid);
+
+    errno = EPERM;
+
+    return (0);
+  }
+
+  fprintf(stderr,
+          "DEBUG2: Program directory \"%s\" permissions OK "
+         "(0%o/uid=%d/gid=%d).", temp, fileinfo.st_mode, (int)fileinfo.st_uid,
+         (int)fileinfo.st_gid);
+
+ /*
+  * If we get here then we can "safely" run this program...
+  */
+
+  return (1);
+}
+
+
 /*
  * 'cupsdCompareNames()' - Compare two names.
  *
index ad4172f69aa36657b1c58925f508f3d2a4d81efc..d62e7947ce546fef353adb2d18326cfc5798c05b 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Mini-daemon utility definitions for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2011 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -44,6 +44,7 @@ typedef int (*cupsd_compare_func_t)(const void *, const void *);
  * Prototypes...
  */
 
+extern int             cupsdCheckProgram(const char *filename);
 extern int             cupsdCompareNames(const char *s, const char *t);
 extern cups_array_t    *cupsdCreateStringsArray(const char *s);
 extern int             cupsdExec(const char *command, char **argv);