]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - scheduler/policy.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / scheduler / policy.c
index d2c387a99b35e61797733095d9597c94b945dce3..9a68b1a97b582a769e8bf2fc1033759924524d85 100644 (file)
@@ -1,35 +1,14 @@
 /*
- * "$Id: policy.c 177 2006-06-21 00:20:03Z jlovell $"
+ * Policy routines for the CUPS scheduler.
  *
- *   Policy routines for the Common UNIX Printing System (CUPS).
+ * Copyright 2007-2011, 2014 by Apple Inc.
+ * Copyright 1997-2006 by Easy Software Products, all rights reserved.
  *
- *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
- *
- *   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:
- *
- *   cupsdAddPolicy()         - Add a policy to the system.
- *   cupsdAddPolicyOp()       - Add an operation to a policy.
- *   cupsdCheckPolicy()       - Check the IPP operation and username against
- *                              a policy.
- *   cupsdDeleteAllPolicies() - Delete all policies in memory.
- *   cupsdFindPolicy()        - Find a named policy.
- *   cupsdFindPolicyOp()      - Find a policy operation.
+ * 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"
+#include <pwd.h>
+
+
+/*
+ * Local functions...
+ */
+
+static int     compare_ops(cupsd_location_t *a, cupsd_location_t *b);
+static int     compare_policies(cupsd_policy_t *a, cupsd_policy_t *b);
+static void    free_policy(cupsd_policy_t *p);
+static int     hash_op(cupsd_location_t *op);
 
 
 /*
- * 'AddPolicy()' - Add a policy to the system.
+ * 'cupsdAddPolicy()' - Add a policy to the system.
  */
 
 cupsd_policy_t *                       /* O - Policy */
 cupsdAddPolicy(const char *policy)     /* I - Name of policy */
 {
-  cupsd_policy_t       *temp,          /* Pointer to policy */
-                       **tempa;        /* Pointer to policy array */
+  cupsd_policy_t       *temp;          /* Pointer to policy */
 
 
-  if (policy == NULL)
+  if (!policy)
     return (NULL);
 
-  if (NumPolicies == 0)
-    tempa = malloc(sizeof(cupsd_policy_t *));
-  else
-    tempa = realloc(Policies, sizeof(cupsd_policy_t *) * (NumPolicies + 1));
+  if (!Policies)
+    Policies = cupsArrayNew3((cups_array_func_t)compare_policies, NULL,
+                            (cups_ahash_func_t)NULL, 0,
+                            (cups_acopy_func_t)NULL,
+                            (cups_afree_func_t)free_policy);
 
-  if (tempa == NULL)
+  if (!Policies)
     return (NULL);
 
-  Policies = tempa;
-  tempa    += NumPolicies;
-
   if ((temp = calloc(1, sizeof(cupsd_policy_t))) != NULL)
   {
-    temp->name = strdup(policy);
-    *tempa     = temp;
-
-    NumPolicies ++;
+    cupsdSetString(&temp->name, policy);
+    cupsArrayAdd(Policies, temp);
   }
 
   return (temp);
@@ -85,90 +70,30 @@ cupsdAddPolicyOp(cupsd_policy_t   *p,       /* I - Policy */
                  cupsd_location_t *po, /* I - Policy operation to copy */
                  ipp_op_t         op)  /* I - IPP operation code */
 {
-  int                  i;              /* Looping var */
-  cupsd_location_t     *temp,          /* New policy operation */
-                       **tempa;        /* New policy operation array */
-  char                 name[1024];     /* Interface name */
+  cupsd_location_t     *temp;          /* New policy operation */
 
 
   cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddPolicyOp(p=%p, po=%p, op=%x(%s))",
                   p, po, op, ippOpString(op));
 
-  if (p == NULL)
+  if (!p)
     return (NULL);
 
-  if (p->num_ops == 0)
-    tempa = malloc(sizeof(cupsd_location_t *));
-  else
-    tempa = realloc(p->ops, sizeof(cupsd_location_t *) * (p->num_ops + 1));
+  if (!p->ops)
+    p->ops = cupsArrayNew3((cups_array_func_t)compare_ops, NULL,
+                           (cups_ahash_func_t)hash_op, 128,
+                          (cups_acopy_func_t)NULL,
+                          (cups_afree_func_t)cupsdFreeLocation);
 
-  if (tempa == NULL)
+  if (!p->ops)
     return (NULL);
 
-  p->ops = tempa;
-
-  if ((temp = calloc(1, sizeof(cupsd_location_t))) != NULL)
+  if ((temp = cupsdCopyLocation(po)) != NULL)
   {
-    p->ops            = tempa;
-    tempa[p->num_ops] = temp;
-    p->num_ops ++;
-
     temp->op    = op;
-    temp->limit = AUTH_LIMIT_IPP;
+    temp->limit = CUPSD_AUTH_LIMIT_IPP;
 
-    if (po)
-    {
-     /*
-      * Copy the specified policy to the new one...
-      */
-
-      temp->order_type = po->order_type;
-      temp->type       = po->type;
-      temp->level      = po->level;
-      temp->satisfy    = po->satisfy;
-      temp->encryption = po->encryption;
-
-      for (i = 0; i < po->num_names; i ++)
-        cupsdAddName(temp, po->names[i]);
-
-      for (i = 0; i < po->num_allow; i ++)
-        switch (po->allow[i].type)
-       {
-         case AUTH_IP :
-             cupsdAllowIP(temp, po->allow[i].mask.ip.address,
-                     po->allow[i].mask.ip.netmask);
-             break;
-
-          case AUTH_INTERFACE :
-             snprintf(name, sizeof(name), "@IF(%s)",
-                      po->allow[i].mask.name.name);
-              cupsdAllowHost(temp, name);
-             break;
-
-          default :
-              cupsdAllowHost(temp, po->allow[i].mask.name.name);
-             break;
-        }
-
-      for (i = 0; i < po->num_deny; i ++)
-        switch (po->deny[i].type)
-       {
-         case AUTH_IP :
-             cupsdDenyIP(temp, po->deny[i].mask.ip.address,
-                     po->deny[i].mask.ip.netmask);
-             break;
-
-          case AUTH_INTERFACE :
-             snprintf(name, sizeof(name), "@IF(%s)",
-                      po->deny[i].mask.name.name);
-              cupsdDenyHost(temp, name);
-             break;
-
-          default :
-              cupsdDenyHost(temp, po->deny[i].mask.name.name);
-             break;
-        }
-    }
+    cupsArrayAdd(p->ops, temp);
   }
 
   return (temp);
@@ -193,9 +118,9 @@ cupsdCheckPolicy(cupsd_policy_t *p, /* I - Policy */
 
   if (!p || !con)
   {
-    cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdCheckPolicy: p=%p, con=%p!", p, con);
+    cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdCheckPolicy: p=%p, con=%p.", p, con);
 
-    return (0);
+    return ((http_status_t)0);
   }
 
  /*
@@ -204,8 +129,8 @@ cupsdCheckPolicy(cupsd_policy_t *p, /* I - Policy */
 
   if ((po = cupsdFindPolicyOp(p, con->request->request.op.operation_id)) == NULL)
   {
-    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckPolicy: No matching operation, returning 0!");
-    return (0);
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckPolicy: No matching operation, returning 0.");
+    return ((http_status_t)0);
   }
 
   con->best = po;
@@ -225,29 +150,30 @@ cupsdCheckPolicy(cupsd_policy_t *p,       /* I - Policy */
 void
 cupsdDeleteAllPolicies(void)
 {
-  int                  i, j;           /* Looping vars */
-  cupsd_policy_t       **p;            /* Current policy */
-  cupsd_location_t     **po;           /* Current policy op */
+  cupsd_printer_t      *printer;       /* Current printer */
 
 
-  if (NumPolicies == 0)
+  if (!Policies)
     return;
 
-  for (i = NumPolicies, p = Policies; i > 0; i --, p ++)
-  {
-    for (j = (*p)->num_ops, po = (*p)->ops; j > 0; j --, po ++)
-      cupsdDeleteLocation(*po);
+ /*
+  * First clear the policy pointers for all printers...
+  */
 
-    if ((*p)->num_ops > 0)
-      free((*p)->ops);
+  for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
+       printer;
+       printer = (cupsd_printer_t *)cupsArrayNext(Printers))
+    printer->op_policy_ptr = NULL;
 
-    free(*p);
-  }
+  DefaultPolicyPtr = NULL;
 
-  free(Policies);
+ /*
+  * Then free all of the policies...
+  */
+
+  cupsArrayDelete(Policies);
 
-  NumPolicies = 0;
-  Policies    = NULL;
+  Policies = NULL;
 }
 
 
@@ -258,26 +184,22 @@ cupsdDeleteAllPolicies(void)
 cupsd_policy_t *                       /* O - Policy */
 cupsdFindPolicy(const char *policy)    /* I - Name of policy */
 {
-  int                  i;              /* Looping var */
-  cupsd_policy_t       **p;            /* Current policy */
+  cupsd_policy_t       key;            /* Search key */
 
 
  /*
   * Range check...
   */
 
-  if (policy == NULL)
+  if (!policy)
     return (NULL);
 
  /*
-  * Check the operation against the available policies...
+  * Look it up...
   */
 
-  for (i = NumPolicies, p = Policies; i > 0; i --, p ++)
-    if (!strcasecmp(policy, (*p)->name))
-      return (*p);
-
-  return (NULL);
+  key.name = (char *)policy;
+  return ((cupsd_policy_t *)cupsArrayFind(Policies, &key));
 }
 
 
@@ -289,46 +211,290 @@ cupsd_location_t *                       /* O - Policy operation */
 cupsdFindPolicyOp(cupsd_policy_t *p,   /* I - Policy */
                   ipp_op_t       op)   /* I - IPP operation */
 {
-  int                  i;              /* Looping var */
-  cupsd_location_t     **po;           /* Current policy operation */
+  cupsd_location_t     key,            /* Search key... */
+                       *po;            /* Current policy operation */
 
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp(p=%p, op=%x(%s))\n",
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp(p=%p, op=%x(%s))",
                   p, op, ippOpString(op));
 
  /*
   * Range check...
   */
 
-  if (p == NULL)
+  if (!p)
     return (NULL);
 
  /*
   * Check the operation against the available policies...
   */
 
-  for (i = p->num_ops, po = p->ops; i > 0; i --, po ++)
-    if ((*po)->op == op)
+  key.op = op;
+  if ((po = (cupsd_location_t *)cupsArrayFind(p->ops, &key)) != NULL)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                   "cupsdFindPolicyOp: Found exact match...");
+    return (po);
+  }
+
+  key.op = IPP_ANY_OPERATION;
+  if ((po = (cupsd_location_t *)cupsArrayFind(p->ops, &key)) != NULL)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                   "cupsdFindPolicyOp: Found wildcard match...");
+    return (po);
+  }
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp: No match found.");
+
+  return (NULL);
+}
+
+
+/*
+ * 'cupsdGetPrivateAttrs()' - Get the private attributes for the current
+ *                            request.
+ */
+
+cups_array_t *                         /* O - Array or NULL for no restrictions */
+cupsdGetPrivateAttrs(
+    cupsd_policy_t  *policy,           /* I - Policy */
+    cupsd_client_t  *con,              /* I - Client connection */
+    cupsd_printer_t *printer,          /* I - Printer, if any */
+    const char      *owner)            /* I - Owner of object */
+{
+  char         *name;                  /* Current name in access list */
+  cups_array_t *access_ptr,            /* Access array */
+               *attrs_ptr;             /* Attributes array */
+  const char   *username;              /* Username associated with request */
+  ipp_attribute_t *attr;               /* Attribute from request */
+  struct passwd        *pw;                    /* User info */
+
+
+#ifdef DEBUG
+  cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                  "cupsdGetPrivateAttrs(policy=%p(%s), con=%p(%d), "
+                 "printer=%p(%s), owner=\"%s\")", policy, policy->name, con,
+                 con->number, printer, printer ? printer->name : "", owner);
+#endif /* DEBUG */
+
+  if (!policy)
+  {
+    cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdGetPrivateAttrs: policy=%p, con=%p, printer=%p, owner=\"%s\", DefaultPolicyPtr=%p: This should never happen, please report a bug.", policy, con, printer, owner, DefaultPolicyPtr);
+    policy = DefaultPolicyPtr;
+  }
+
+ /*
+  * Get the access and attributes lists that correspond to the request...
+  */
+
+#ifdef DEBUG
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: %s",
+                  ippOpString(con->request->request.op.operation_id));
+#endif /* DEBUG */
+
+  switch (con->request->request.op.operation_id)
+  {
+    case IPP_GET_SUBSCRIPTIONS :
+    case IPP_GET_SUBSCRIPTION_ATTRIBUTES :
+    case IPP_GET_NOTIFICATIONS :
+        access_ptr = policy->sub_access;
+       attrs_ptr  = policy->sub_attrs;
+       break;
+
+    default :
+        access_ptr = policy->job_access;
+       attrs_ptr  = policy->job_attrs;
+        break;
+  }
+
+ /*
+  * If none of the attributes are private, return NULL now...
+  */
+
+  if ((name = (char *)cupsArrayFirst(attrs_ptr)) != NULL &&
+      !_cups_strcasecmp(name, "none"))
+  {
+#ifdef DEBUG
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+    return (NULL);
+  }
+
+ /*
+  * Otherwise check the user against the access list...
+  */
+
+  if (con->username[0])
+    username = con->username;
+  else if ((attr = ippFindAttribute(con->request, "requesting-user-name",
+                                    IPP_TAG_NAME)) != NULL)
+    username = attr->values[0].string.text;
+  else
+    username = "anonymous";
+
+  if (username[0])
+  {
+    pw = getpwnam(username);
+    endpwent();
+  }
+  else
+    pw = NULL;
+
+#ifdef DEBUG
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: username=\"%s\"",
+                  username);
+#endif /* DEBUG */
+
+ /*
+  * Otherwise check the user against the access list...
+  */
+
+  for (name = (char *)cupsArrayFirst(access_ptr);
+       name;
+       name = (char *)cupsArrayNext(access_ptr))
+  {
+#ifdef DEBUG
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: name=%s", name);
+#endif /* DEBUG */
+
+    if (printer && !_cups_strcasecmp(name, "@ACL"))
+    {
+      char     *acl;                   /* Current ACL user/group */
+
+      for (acl = (char *)cupsArrayFirst(printer->users);
+          acl;
+          acl = (char *)cupsArrayNext(printer->users))
+      {
+       if (acl[0] == '@')
+       {
+        /*
+         * Check group membership...
+         */
+
+         if (cupsdCheckGroup(username, pw, acl + 1))
+           break;
+       }
+       else if (acl[0] == '#')
+       {
+        /*
+         * Check UUID...
+         */
+
+         if (cupsdCheckGroup(username, pw, acl))
+           break;
+       }
+       else if (!_cups_strcasecmp(username, acl))
+         break;
+      }
+    }
+    else if (owner && !_cups_strcasecmp(name, "@OWNER") &&
+             !_cups_strcasecmp(username, owner))
     {
+#ifdef DEBUG
       cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                      "cupsdFindPolicyOp: Found exact match...");
-      return (*po);
+                     "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+      return (NULL);
     }
+    else if (!_cups_strcasecmp(name, "@SYSTEM"))
+    {
+      int i;                           /* Looping var */
+
+      for (i = 0; i < NumSystemGroups; i ++)
+       if (cupsdCheckGroup(username, pw, SystemGroups[i]))
+       {
+#ifdef DEBUG
+         cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                         "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
 
-  for (i = p->num_ops, po = p->ops; i > 0; i --, po ++)
-    if ((*po)->op == IPP_ANY_OPERATION)
+         return (NULL);
+       }
+    }
+    else if (name[0] == '@')
     {
-      cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                      "cupsdFindPolicyOp: Found wildcard match...");
-      return (*po);
+      if (cupsdCheckGroup(username, pw, name + 1))
+      {
+#ifdef DEBUG
+        cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                       "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+       return (NULL);
+      }
+    }
+    else if (!_cups_strcasecmp(username, name))
+    {
+#ifdef DEBUG
+      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning NULL.");
+#endif /* DEBUG */
+
+      return (NULL);
     }
+  }
+
+ /*
+  * No direct access, so return private attributes list...
+  */
 
-  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp: No match found!");
+#ifdef DEBUG
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning list.");
+#endif /* DEBUG */
 
-  return (NULL);
+  return (attrs_ptr);
+}
+
+
+/*
+ * 'compare_ops()' - Compare two operations.
+ */
+
+static int                             /* O - Result of comparison */
+compare_ops(cupsd_location_t *a,       /* I - First operation */
+            cupsd_location_t *b)       /* I - Second operation */
+{
+  return (a->op - b->op);
 }
 
 
 /*
- * End of "$Id: policy.c 177 2006-06-21 00:20:03Z jlovell $".
+ * 'compare_policies()' - Compare two policies.
  */
+
+static int                             /* O - Result of comparison */
+compare_policies(cupsd_policy_t *a,    /* I - First policy */
+                 cupsd_policy_t *b)    /* I - Second policy */
+{
+  return (_cups_strcasecmp(a->name, b->name));
+}
+
+
+/*
+ * 'free_policy()' - Free the memory used by a policy.
+ */
+
+static void
+free_policy(cupsd_policy_t *p)         /* I - Policy to free */
+{
+  cupsArrayDelete(p->job_access);
+  cupsArrayDelete(p->job_attrs);
+  cupsArrayDelete(p->sub_access);
+  cupsArrayDelete(p->sub_attrs);
+  cupsArrayDelete(p->ops);
+  cupsdClearString(&p->name);
+  free(p);
+}
+
+
+/*
+ * 'hash_op()' - Generate a lookup hash for the operation.
+ */
+
+static int                             /* O - Hash value */
+hash_op(cupsd_location_t *op)          /* I - Operation */
+{
+  return (((op->op >> 6) & 0x40) | (op->op & 0x3f));
+}