blob: 25204ee89a51907dd91d2985a98ecbf8135fdece [file] [log] [blame]
/*
* "$Id: policy.c 6895 2007-08-30 00:09:27Z mike $"
*
* Policy routines for the Common UNIX Printing System (CUPS).
*
* Copyright 2007 by Apple Inc.
* Copyright 1997-2006 by Easy Software Products, all rights reserved.
*
* 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/".
*
* 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.
*/
/*
* Include necessary headers...
*/
#include "cupsd.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 int hash_op(cupsd_location_t *op);
/*
* 'AddPolicy()' - 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 */
if (!policy)
return (NULL);
if (!Policies)
Policies = cupsArrayNew((cups_array_func_t)compare_policies, NULL);
if (!Policies)
return (NULL);
if ((temp = calloc(1, sizeof(cupsd_policy_t))) != NULL)
{
cupsdSetString(&temp->name, policy);
cupsArrayAdd(Policies, temp);
}
return (temp);
}
/*
* 'cupsdAddPolicyOp()' - Add an operation to a policy.
*/
cupsd_location_t * /* O - New policy operation */
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 */
char name[1024]; /* Interface name */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddPolicyOp(p=%p, po=%p, op=%x(%s))",
p, po, op, ippOpString(op));
if (!p)
return (NULL);
if (!p->ops)
p->ops = cupsArrayNew2((cups_array_func_t)compare_ops, NULL,
(cups_ahash_func_t)hash_op, 128);
if (!p->ops)
return (NULL);
if ((temp = calloc(1, sizeof(cupsd_location_t))) != NULL)
{
temp->op = op;
temp->limit = AUTH_LIMIT_IPP;
cupsArrayAdd(p->ops, temp);
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;
}
}
}
return (temp);
}
/*
* 'cupsdCheckPolicy()' - Check the IPP operation and username against a policy.
*/
http_status_t /* I - 1 if OK, 0 otherwise */
cupsdCheckPolicy(cupsd_policy_t *p, /* I - Policy */
cupsd_client_t *con, /* I - Client connection */
const char *owner) /* I - Owner of object */
{
cupsd_location_t *po; /* Current policy operation */
/*
* Range check...
*/
if (!p || !con)
{
cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdCheckPolicy: p=%p, con=%p!", p, con);
return ((http_status_t)0);
}
/*
* Find a match for the operation...
*/
if ((po = cupsdFindPolicyOp(p, con->request->request.op.operation_id)) == NULL)
{
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckPolicy: No matching operation, returning 0!");
return ((http_status_t)0);
}
con->best = po;
/*
* Return the status of the check...
*/
return (cupsdIsAuthorized(con, owner));
}
/*
* 'cupsdDeleteAllPolicies()' - Delete all policies in memory.
*/
void
cupsdDeleteAllPolicies(void)
{
cupsd_policy_t *p; /* Current policy */
cupsd_location_t *po; /* Current policy op */
if (!Policies)
return;
for (p = (cupsd_policy_t *)cupsArrayFirst(Policies);
p;
p = (cupsd_policy_t *)cupsArrayNext(Policies))
{
for (po = (cupsd_location_t *)cupsArrayFirst(p->ops);
po;
po = (cupsd_location_t *)cupsArrayNext(p->ops))
cupsdDeleteLocation(po);
cupsArrayDelete(p->ops);
cupsdClearString(&p->name);
free(p);
}
cupsArrayDelete(Policies);
Policies = NULL;
}
/*
* 'cupsdFindPolicy()' - Find a named policy.
*/
cupsd_policy_t * /* O - Policy */
cupsdFindPolicy(const char *policy) /* I - Name of policy */
{
cupsd_policy_t key; /* Search key */
/*
* Range check...
*/
if (!policy)
return (NULL);
/*
* Look it up...
*/
key.name = (char *)policy;
return ((cupsd_policy_t *)cupsArrayFind(Policies, &key));
}
/*
* 'cupsdFindPolicyOp()' - Find a policy operation.
*/
cupsd_location_t * /* O - Policy operation */
cupsdFindPolicyOp(cupsd_policy_t *p, /* I - Policy */
ipp_op_t op) /* I - IPP operation */
{
cupsd_location_t key, /* Search key... */
*po; /* Current policy operation */
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp(p=%p, op=%x(%s))\n",
p, op, ippOpString(op));
/*
* Range check...
*/
if (!p)
return (NULL);
/*
* Check the operation against the available policies...
*/
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);
}
/*
* '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);
}
/*
* '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 (strcasecmp(a->name, b->name));
}
/*
* '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));
}
/*
* End of "$Id: policy.c 6895 2007-08-30 00:09:27Z mike $".
*/