#include "cupsd.h"
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);
cupsd_policy_t *
cupsdAddPolicy(const char *policy)
{
cupsd_policy_t *temp;
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);
}
cupsd_location_t *
cupsdAddPolicyOp(cupsd_policy_t *p,
cupsd_location_t *po,
ipp_op_t op)
{
int i;
cupsd_location_t *temp;
char name[1024];
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 = CUPSD_AUTH_LIMIT_IPP;
cupsArrayAdd(p->ops, temp);
if (po)
{
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 CUPSD_AUTH_IP :
cupsdAllowIP(temp, po->allow[i].mask.ip.address,
po->allow[i].mask.ip.netmask);
break;
case CUPSD_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 CUPSD_AUTH_IP :
cupsdDenyIP(temp, po->deny[i].mask.ip.address,
po->deny[i].mask.ip.netmask);
break;
case CUPSD_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);
}
http_status_t
cupsdCheckPolicy(cupsd_policy_t *p,
cupsd_client_t *con,
const char *owner)
{
cupsd_location_t *po;
if (!p || !con)
{
cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdCheckPolicy: p=%p, con=%p!", p, con);
return ((http_status_t)0);
}
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 (cupsdIsAuthorized(con, owner));
}
void
cupsdDeleteAllPolicies(void)
{
cupsd_policy_t *p;
cupsd_location_t *po;
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;
}
cupsd_policy_t *
cupsdFindPolicy(const char *policy)
{
cupsd_policy_t key;
if (!policy)
return (NULL);
key.name = (char *)policy;
return ((cupsd_policy_t *)cupsArrayFind(Policies, &key));
}
cupsd_location_t *
cupsdFindPolicyOp(cupsd_policy_t *p,
ipp_op_t op)
{
cupsd_location_t key,
*po;
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp(p=%p, op=%x(%s))",
p, op, ippOpString(op));
if (!p)
return (NULL);
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);
}
static int
compare_ops(cupsd_location_t *a,
cupsd_location_t *b)
{
return (a->op - b->op);
}
static int
compare_policies(cupsd_policy_t *a,
cupsd_policy_t *b)
{
return (strcasecmp(a->name, b->name));
}
static int
hash_op(cupsd_location_t *op)
{
return (((op->op >> 6) & 0x40) | (op->op & 0x3f));
}