2 * Policy routines for the CUPS scheduler.
4 * Copyright 2007-2011, 2014 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
11 * Include necessary headers...
22 static int compare_ops(cupsd_location_t
*a
, cupsd_location_t
*b
);
23 static int compare_policies(cupsd_policy_t
*a
, cupsd_policy_t
*b
);
24 static void free_policy(cupsd_policy_t
*p
);
25 static int hash_op(cupsd_location_t
*op
);
29 * 'cupsdAddPolicy()' - Add a policy to the system.
32 cupsd_policy_t
* /* O - Policy */
33 cupsdAddPolicy(const char *policy
) /* I - Name of policy */
35 cupsd_policy_t
*temp
; /* Pointer to policy */
42 Policies
= cupsArrayNew3((cups_array_func_t
)compare_policies
, NULL
,
43 (cups_ahash_func_t
)NULL
, 0,
44 (cups_acopy_func_t
)NULL
,
45 (cups_afree_func_t
)free_policy
);
50 if ((temp
= calloc(1, sizeof(cupsd_policy_t
))) != NULL
)
52 cupsdSetString(&temp
->name
, policy
);
53 cupsArrayAdd(Policies
, temp
);
61 * 'cupsdAddPolicyOp()' - Add an operation to a policy.
64 cupsd_location_t
* /* O - New policy operation */
65 cupsdAddPolicyOp(cupsd_policy_t
*p
, /* I - Policy */
66 cupsd_location_t
*po
, /* I - Policy operation to copy */
67 ipp_op_t op
) /* I - IPP operation code */
69 cupsd_location_t
*temp
; /* New policy operation */
72 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdAddPolicyOp(p=%p, po=%p, op=%x(%s))",
73 p
, po
, op
, ippOpString(op
));
79 p
->ops
= cupsArrayNew3((cups_array_func_t
)compare_ops
, NULL
,
80 (cups_ahash_func_t
)hash_op
, 128,
81 (cups_acopy_func_t
)NULL
,
82 (cups_afree_func_t
)cupsdFreeLocation
);
87 if ((temp
= cupsdCopyLocation(po
)) != NULL
)
90 temp
->limit
= CUPSD_AUTH_LIMIT_IPP
;
92 cupsArrayAdd(p
->ops
, temp
);
100 * 'cupsdCheckPolicy()' - Check the IPP operation and username against a policy.
103 http_status_t
/* I - 1 if OK, 0 otherwise */
104 cupsdCheckPolicy(cupsd_policy_t
*p
, /* I - Policy */
105 cupsd_client_t
*con
, /* I - Client connection */
106 const char *owner
) /* I - Owner of object */
108 cupsd_location_t
*po
; /* Current policy operation */
117 cupsdLogMessage(CUPSD_LOG_CRIT
, "cupsdCheckPolicy: p=%p, con=%p.", p
, con
);
119 return ((http_status_t
)0);
123 * Find a match for the operation...
126 if ((po
= cupsdFindPolicyOp(p
, con
->request
->request
.op
.operation_id
)) == NULL
)
128 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdCheckPolicy: No matching operation, returning 0.");
129 return ((http_status_t
)0);
135 * Return the status of the check...
138 return (cupsdIsAuthorized(con
, owner
));
143 * 'cupsdDeleteAllPolicies()' - Delete all policies in memory.
147 cupsdDeleteAllPolicies(void)
149 cupsd_printer_t
*printer
; /* Current printer */
156 * First clear the policy pointers for all printers...
159 for (printer
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
161 printer
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
162 printer
->op_policy_ptr
= NULL
;
164 DefaultPolicyPtr
= NULL
;
167 * Then free all of the policies...
170 cupsArrayDelete(Policies
);
177 * 'cupsdFindPolicy()' - Find a named policy.
180 cupsd_policy_t
* /* O - Policy */
181 cupsdFindPolicy(const char *policy
) /* I - Name of policy */
183 cupsd_policy_t key
; /* Search key */
197 key
.name
= (char *)policy
;
198 return ((cupsd_policy_t
*)cupsArrayFind(Policies
, &key
));
203 * 'cupsdFindPolicyOp()' - Find a policy operation.
206 cupsd_location_t
* /* O - Policy operation */
207 cupsdFindPolicyOp(cupsd_policy_t
*p
, /* I - Policy */
208 ipp_op_t op
) /* I - IPP operation */
210 cupsd_location_t key
, /* Search key... */
211 *po
; /* Current policy operation */
214 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdFindPolicyOp(p=%p, op=%x(%s))",
215 p
, op
, ippOpString(op
));
225 * Check the operation against the available policies...
229 if ((po
= (cupsd_location_t
*)cupsArrayFind(p
->ops
, &key
)) != NULL
)
231 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
232 "cupsdFindPolicyOp: Found exact match...");
236 key
.op
= IPP_ANY_OPERATION
;
237 if ((po
= (cupsd_location_t
*)cupsArrayFind(p
->ops
, &key
)) != NULL
)
239 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
240 "cupsdFindPolicyOp: Found wildcard match...");
244 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdFindPolicyOp: No match found.");
251 * 'cupsdGetPrivateAttrs()' - Get the private attributes for the current
255 cups_array_t
* /* O - Array or NULL for no restrictions */
256 cupsdGetPrivateAttrs(
257 cupsd_policy_t
*policy
, /* I - Policy */
258 cupsd_client_t
*con
, /* I - Client connection */
259 cupsd_printer_t
*printer
, /* I - Printer, if any */
260 const char *owner
) /* I - Owner of object */
262 char *name
; /* Current name in access list */
263 cups_array_t
*access_ptr
, /* Access array */
264 *attrs_ptr
; /* Attributes array */
265 const char *username
; /* Username associated with request */
266 ipp_attribute_t
*attr
; /* Attribute from request */
267 struct passwd
*pw
; /* User info */
271 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
272 "cupsdGetPrivateAttrs(policy=%p(%s), con=%p(%d), "
273 "printer=%p(%s), owner=\"%s\")", policy
, policy
->name
, con
,
274 con
->number
, printer
, printer
? printer
->name
: "", owner
);
279 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
);
280 policy
= DefaultPolicyPtr
;
284 * Get the access and attributes lists that correspond to the request...
288 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: %s",
289 ippOpString(con
->request
->request
.op
.operation_id
));
292 switch (con
->request
->request
.op
.operation_id
)
294 case IPP_GET_SUBSCRIPTIONS
:
295 case IPP_GET_SUBSCRIPTION_ATTRIBUTES
:
296 case IPP_GET_NOTIFICATIONS
:
297 access_ptr
= policy
->sub_access
;
298 attrs_ptr
= policy
->sub_attrs
;
302 access_ptr
= policy
->job_access
;
303 attrs_ptr
= policy
->job_attrs
;
308 * If none of the attributes are private, return NULL now...
311 if ((name
= (char *)cupsArrayFirst(attrs_ptr
)) != NULL
&&
312 !_cups_strcasecmp(name
, "none"))
315 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning NULL.");
322 * Otherwise check the user against the access list...
325 if (con
->username
[0])
326 username
= con
->username
;
327 else if ((attr
= ippFindAttribute(con
->request
, "requesting-user-name",
328 IPP_TAG_NAME
)) != NULL
)
329 username
= attr
->values
[0].string
.text
;
331 username
= "anonymous";
335 pw
= getpwnam(username
);
342 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: username=\"%s\"",
347 * Otherwise check the user against the access list...
350 for (name
= (char *)cupsArrayFirst(access_ptr
);
352 name
= (char *)cupsArrayNext(access_ptr
))
355 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: name=%s", name
);
358 if (printer
&& !_cups_strcasecmp(name
, "@ACL"))
360 char *acl
; /* Current ACL user/group */
362 for (acl
= (char *)cupsArrayFirst(printer
->users
);
364 acl
= (char *)cupsArrayNext(printer
->users
))
369 * Check group membership...
372 if (cupsdCheckGroup(username
, pw
, acl
+ 1))
375 else if (acl
[0] == '#')
381 if (cupsdCheckGroup(username
, pw
, acl
))
384 else if (!_cups_strcasecmp(username
, acl
))
388 else if (owner
&& !_cups_strcasecmp(name
, "@OWNER") &&
389 !_cups_strcasecmp(username
, owner
))
392 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
393 "cupsdGetPrivateAttrs: Returning NULL.");
398 else if (!_cups_strcasecmp(name
, "@SYSTEM"))
400 int i
; /* Looping var */
402 for (i
= 0; i
< NumSystemGroups
; i
++)
403 if (cupsdCheckGroup(username
, pw
, SystemGroups
[i
]))
406 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
407 "cupsdGetPrivateAttrs: Returning NULL.");
413 else if (name
[0] == '@')
415 if (cupsdCheckGroup(username
, pw
, name
+ 1))
418 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
419 "cupsdGetPrivateAttrs: Returning NULL.");
425 else if (!_cups_strcasecmp(username
, name
))
428 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning NULL.");
436 * No direct access, so return private attributes list...
440 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning list.");
448 * 'compare_ops()' - Compare two operations.
451 static int /* O - Result of comparison */
452 compare_ops(cupsd_location_t
*a
, /* I - First operation */
453 cupsd_location_t
*b
) /* I - Second operation */
455 return (a
->op
- b
->op
);
460 * 'compare_policies()' - Compare two policies.
463 static int /* O - Result of comparison */
464 compare_policies(cupsd_policy_t
*a
, /* I - First policy */
465 cupsd_policy_t
*b
) /* I - Second policy */
467 return (_cups_strcasecmp(a
->name
, b
->name
));
472 * 'free_policy()' - Free the memory used by a policy.
476 free_policy(cupsd_policy_t
*p
) /* I - Policy to free */
478 cupsArrayDelete(p
->job_access
);
479 cupsArrayDelete(p
->job_attrs
);
480 cupsArrayDelete(p
->sub_access
);
481 cupsArrayDelete(p
->sub_attrs
);
482 cupsArrayDelete(p
->ops
);
483 cupsdClearString(&p
->name
);
489 * 'hash_op()' - Generate a lookup hash for the operation.
492 static int /* O - Hash value */
493 hash_op(cupsd_location_t
*op
) /* I - Operation */
495 return (((op
->op
>> 6) & 0x40) | (op
->op
& 0x3f));