]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/cert.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / scheduler / cert.c
index aa8b6ca50f52c960f23ddc12f056cd846554f0c0..17f5bd5dc5befb1db43af77d65b562c29dda4558 100644 (file)
@@ -1,35 +1,14 @@
 /*
- * "$Id: cert.c 4966 2006-01-23 00:41:22Z mike $"
+ * Authentication certificate routines for the CUPS scheduler.
  *
- *   Authentication certificate routines for the Common UNIX
- *   Printing System (CUPS).
+ * Copyright 2007-2015 by Apple Inc.
+ * Copyright 1997-2006 by Easy Software Products.
  *
- *   Copyright 1997-2005 by Easy Software Products.
- *
- *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products and are protected by Federal
- *   copyright law.  Distribution and use rights are outlined in the file
- *   "LICENSE.txt" which should have been included with this file.  If this
- *   file is missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
- *
- * Contents:
- *
- *   cupsdAddCert()        - Add a certificate.
- *   cupsdDeleteCert()     - Delete a single certificate.
- *   cupsdDeleteAllCerts() - Delete all certificates...
- *   cupsdFindCert()       - Find a certificate.
- *   cupsdInitCerts()      - Initialize the certificate "system" and root
- *                           certificate.
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file.  If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
  */
 
 /*
 #include "cupsd.h"
 #ifdef HAVE_ACL_INIT
 #  include <sys/acl.h>
-#  include <membership.h>
+#  ifdef HAVE_MEMBERSHIP_H
+#    include <membership.h>
+#  endif /* HAVE_MEMBERSHIP_H */
 #endif /* HAVE_ACL_INIT */
 
 
+/*
+ * Local functions...
+ */
+
+static int     ctcompare(const char *a, const char *b);
+
+
 /*
  * 'cupsdAddCert()' - Add a certificate.
  */
 
 void
 cupsdAddCert(int        pid,           /* I - Process ID */
-             const char *username)     /* I - Username */
+             const char *username,     /* I - Username */
+             int        type)          /* I - AuthType for username */
 {
   int          i;                      /* Looping var */
   cupsd_cert_t *cert;                  /* Current certificate */
@@ -59,8 +48,7 @@ cupsdAddCert(int        pid,          /* I - Process ID */
                                        /* Hex constants... */
 
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                  "cupsdAddCert: adding certificate for pid %d", pid);
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "cupsdAddCert: Adding certificate for PID %d", pid);
 
  /*
   * Allocate memory for the certificate...
@@ -73,11 +61,12 @@ cupsdAddCert(int        pid,                /* I - Process ID */
   * Fill in the certificate information...
   */
 
-  cert->pid = pid;
+  cert->pid  = pid;
+  cert->type = type;
   strlcpy(cert->username, username, sizeof(cert->username));
 
   for (i = 0; i < 32; i ++)
-    cert->certificate[i] = hex[random() & 15];
+    cert->certificate[i] = hex[CUPS_RAND() & 15];
 
  /*
   * Save the certificate to a file readable only by the User and Group
@@ -90,7 +79,7 @@ cupsdAddCert(int        pid,          /* I - Process ID */
   if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0400)) < 0)
   {
     cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "cupsdAddCert: Unable to create certificate file %s - %s",
+                    "Unable to create certificate file %s - %s",
                     filename, strerror(errno));
     free(cert);
     return;
@@ -102,7 +91,11 @@ cupsdAddCert(int        pid,                /* I - Process ID */
     acl_t              acl;            /* ACL information */
     acl_entry_t                entry;          /* ACL entry */
     acl_permset_t      permset;        /* Permissions */
+#  ifdef HAVE_MBR_UID_TO_UUID
     uuid_t             group;          /* Group ID */
+#  endif /* HAVE_MBR_UID_TO_UUID */
+    static int         acls_not_supported = 0;
+                                       /* Only warn once */
 #endif /* HAVE_ACL_INIT */
 
 
@@ -113,6 +106,8 @@ cupsdAddCert(int        pid,                /* I - Process ID */
     fchmod(fd, 0440);
     fchown(fd, RunUser, SystemGroupIDs[0]);
 
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddCert: NumSystemGroups=%d", NumSystemGroups);
+
 #ifdef HAVE_ACL_INIT
     if (NumSystemGroups > 1)
     {
@@ -121,6 +116,13 @@ cupsdAddCert(int        pid,               /* I - Process ID */
       * groups can access it...
       */
 
+      int      j;                      /* Looping var */
+
+#  ifdef HAVE_MBR_UID_TO_UUID
+     /*
+      * On MacOS X, ACLs use UUIDs instead of GIDs...
+      */
+
       acl = acl_init(NumSystemGroups - 1);
 
       for (i = 1; i < NumSystemGroups; i ++)
@@ -129,6 +131,13 @@ cupsdAddCert(int        pid,               /* I - Process ID */
         * Add each group ID to the ACL...
        */
 
+        for (j = 0; j < i; j ++)
+         if (SystemGroupIDs[j] == SystemGroupIDs[i])
+            break;
+
+        if (j < i)
+          continue;                    /* Skip duplicate groups */
+
         acl_create_entry(&acl, &entry);
        acl_get_permset(entry, &permset);
        acl_add_perm(permset, ACL_READ_DATA);
@@ -138,10 +147,91 @@ cupsdAddCert(int        pid,              /* I - Process ID */
        acl_set_permset(entry, permset);
       }
 
+#  else
+     /*
+      * POSIX ACLs need permissions for owner, group, other, and mask
+      * in addition to the rest of the system groups...
+      */
+
+      acl = acl_init(NumSystemGroups + 3);
+
+      /* Owner */
+      acl_create_entry(&acl, &entry);
+      acl_get_permset(entry, &permset);
+      acl_add_perm(permset, ACL_READ);
+      acl_set_tag_type(entry, ACL_USER_OBJ);
+      acl_set_permset(entry, permset);
+
+      /* Group */
+      acl_create_entry(&acl, &entry);
+      acl_get_permset(entry, &permset);
+      acl_add_perm(permset, ACL_READ);
+      acl_set_tag_type(entry, ACL_GROUP_OBJ);
+      acl_set_permset(entry, permset);
+
+      /* Others */
+      acl_create_entry(&acl, &entry);
+      acl_get_permset(entry, &permset);
+      acl_add_perm(permset, 0);
+      acl_set_tag_type(entry, ACL_OTHER);
+      acl_set_permset(entry, permset);
+
+      /* Mask */
+      acl_create_entry(&acl, &entry);
+      acl_get_permset(entry, &permset);
+      acl_add_perm(permset, ACL_READ);
+      acl_set_tag_type(entry, ACL_MASK);
+      acl_set_permset(entry, permset);
+
+      for (i = 1; i < NumSystemGroups; i ++)
+      {
+       /*
+        * Add each group ID to the ACL...
+       */
+
+        for (j = 0; j < i; j ++)
+         if (SystemGroupIDs[j] == SystemGroupIDs[i])
+            break;
+
+        if (j < i)
+          continue;                    /* Skip duplicate groups */
+
+        acl_create_entry(&acl, &entry);
+       acl_get_permset(entry, &permset);
+       acl_add_perm(permset, ACL_READ);
+       acl_set_tag_type(entry, ACL_GROUP);
+       acl_set_qualifier(entry, SystemGroupIDs + i);
+       acl_set_permset(entry, permset);
+      }
+
+      if (acl_valid(acl))
+      {
+        char *text, *textptr;          /* Temporary string */
+
+        cupsdLogMessage(CUPSD_LOG_ERROR, "ACL did not validate: %s",
+                       strerror(errno));
+        text = acl_to_text(acl, NULL);
+       for (textptr = strchr(text, '\n');
+            textptr;
+            textptr = strchr(textptr + 1, '\n'))
+         *textptr = ',';
+
+       cupsdLogMessage(CUPSD_LOG_ERROR, "ACL: %s", text);
+       acl_free(text);
+      }
+#  endif /* HAVE_MBR_UID_TO_UUID */
+
       if (acl_set_fd(fd, acl))
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to set ACLs on root certificate \"%s\" - %s",
-                       filename, strerror(errno));
+      {
+       if (errno != EOPNOTSUPP || !acls_not_supported)
+         cupsdLogMessage(CUPSD_LOG_ERROR,
+                         "Unable to set ACLs on root certificate \"%s\" - %s",
+                         filename, strerror(errno));
+
+       if (errno == EOPNOTSUPP)
+         acls_not_supported = 1;
+      }
+
       acl_free(acl);
     }
 #endif /* HAVE_ACL_INIT */
@@ -192,8 +282,7 @@ cupsdDeleteCert(int pid)            /* I - Process ID */
       * Remove this certificate from the list...
       */
 
-      cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                      "cupsdDeleteCert: removing certificate for pid %d", pid);
+      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdDeleteCert: Removing certificate for PID %d.", pid);
 
       DEBUG_printf(("DELETE pid=%d, username=%s, cert=%s\n", cert->pid,
                     cert->username, cert->certificate));
@@ -211,8 +300,7 @@ cupsdDeleteCert(int pid)            /* I - Process ID */
 
       snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, pid);
       if (unlink(filename))
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "cupsdDeleteCert: Unable to remove %s!\n", filename);
+       cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove %s!", filename);
 
       return;
     }
@@ -243,8 +331,7 @@ cupsdDeleteAllCerts(void)
 
     snprintf(filename, sizeof(filename), "%s/certs/%d", StateDir, cert->pid);
     if (unlink(filename))
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "cupsdDeleteAllCerts: Unable to remove %s!\n", filename);
+      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to remove %s!", filename);
 
    /*
     * Free memory...
@@ -254,7 +341,8 @@ cupsdDeleteAllCerts(void)
     free(cert);
   }
 
-  Certs = NULL;
+  Certs        = NULL;
+  RootCertTime = 0;
 }
 
 
@@ -262,21 +350,21 @@ cupsdDeleteAllCerts(void)
  * 'cupsdFindCert()' - Find a certificate.
  */
 
-const char *                           /* O - Matching username or NULL */
+cupsd_cert_t *                         /* O - Matching certificate or NULL */
 cupsdFindCert(const char *certificate) /* I - Certificate */
 {
   cupsd_cert_t *cert;                  /* Current certificate */
 
 
-  DEBUG_printf(("cupsdFindCert(certificate=%s)\n", certificate));
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert(certificate=%s)", certificate);
   for (cert = Certs; cert != NULL; cert = cert->next)
-    if (!strcasecmp(certificate, cert->certificate))
+    if (!ctcompare(certificate, cert->certificate))
     {
-      DEBUG_printf(("    returning %s...\n", cert->username));
-      return (cert->username);
+      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert: Returning \"%s\".", cert->username);
+      return (cert);
     }
 
-  DEBUG_puts("    certificate not found!");
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindCert: Certificate not found.");
 
   return (NULL);
 }
@@ -290,9 +378,8 @@ cupsdFindCert(const char *certificate)      /* I - Certificate */
 void
 cupsdInitCerts(void)
 {
+#ifndef HAVE_ARC4RANDOM
   cups_file_t  *fp;                    /* /dev/random file */
-  unsigned     seed;                   /* Seed for random number generator */
-  struct timeval tod;                  /* Time of day */
 
 
  /*
@@ -302,40 +389,60 @@ cupsdInitCerts(void)
 
   if ((fp = cupsFileOpen("/dev/urandom", "rb")) == NULL)
   {
+    struct timeval tod;                        /* Time of day */
+
    /*
     * Get the time in usecs and use it as the initial seed...
     */
 
     gettimeofday(&tod, NULL);
 
-    seed = (unsigned)(tod.tv_sec + tod.tv_usec);
+    CUPS_SRAND((unsigned)(tod.tv_sec + tod.tv_usec));
   }
   else
   {
+    unsigned   seed;                   /* Seed for random number generator */
+
    /*
     * Read 4 random characters from the random device and use
     * them as the seed...
     */
 
-    seed = cupsFileGetChar(fp);
-    seed = (seed << 8) | cupsFileGetChar(fp);
-    seed = (seed << 8) | cupsFileGetChar(fp);
-    seed = (seed << 8) | cupsFileGetChar(fp);
+    seed = (unsigned)cupsFileGetChar(fp);
+    seed = (seed << 8) | (unsigned)cupsFileGetChar(fp);
+    seed = (seed << 8) | (unsigned)cupsFileGetChar(fp);
+    CUPS_SRAND((seed << 8) | (unsigned)cupsFileGetChar(fp));
 
     cupsFileClose(fp);
   }
-
-  srandom(seed);
+#endif /* !HAVE_ARC4RANDOM */
 
  /*
   * Create a root certificate and return...
   */
 
   if (!RunUser)
-    cupsdAddCert(0, "root");
+    cupsdAddCert(0, "root", cupsdDefaultAuthType());
 }
 
 
 /*
- * End of "$Id: cert.c 4966 2006-01-23 00:41:22Z mike $".
+ * 'ctcompare()' - Compare two strings in constant time.
  */
+
+static int                             /* O - 0 on match, non-zero on non-match */
+ctcompare(const char *a,               /* I - First string */
+          const char *b)               /* I - Second string */
+{
+  int  result = 0;                     /* Result */
+
+
+  while (*a && *b)
+  {
+    result |= *a ^ *b;
+    a ++;
+    b ++;
+  }
+
+  return (result);
+}