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 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
10 * which should have been included with this file. If this file is
11 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * Include necessary headers...
26 static int compare_ops(cupsd_location_t
*a
, cupsd_location_t
*b
);
27 static int compare_policies(cupsd_policy_t
*a
, cupsd_policy_t
*b
);
28 static void free_policy(cupsd_policy_t
*p
);
29 static int hash_op(cupsd_location_t
*op
);
33 * 'cupsdAddPolicy()' - Add a policy to the system.
36 cupsd_policy_t
* /* O - Policy */
37 cupsdAddPolicy(const char *policy
) /* I - Name of policy */
39 cupsd_policy_t
*temp
; /* Pointer to policy */
46 Policies
= cupsArrayNew3((cups_array_func_t
)compare_policies
, NULL
,
47 (cups_ahash_func_t
)NULL
, 0,
48 (cups_acopy_func_t
)NULL
,
49 (cups_afree_func_t
)free_policy
);
54 if ((temp
= calloc(1, sizeof(cupsd_policy_t
))) != NULL
)
56 cupsdSetString(&temp
->name
, policy
);
57 cupsArrayAdd(Policies
, temp
);
65 * 'cupsdAddPolicyOp()' - Add an operation to a policy.
68 cupsd_location_t
* /* O - New policy operation */
69 cupsdAddPolicyOp(cupsd_policy_t
*p
, /* I - Policy */
70 cupsd_location_t
*po
, /* I - Policy operation to copy */
71 ipp_op_t op
) /* I - IPP operation code */
73 cupsd_location_t
*temp
; /* New policy operation */
76 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdAddPolicyOp(p=%p, po=%p, op=%x(%s))",
77 p
, po
, op
, ippOpString(op
));
83 p
->ops
= cupsArrayNew3((cups_array_func_t
)compare_ops
, NULL
,
84 (cups_ahash_func_t
)hash_op
, 128,
85 (cups_acopy_func_t
)NULL
,
86 (cups_afree_func_t
)cupsdFreeLocation
);
91 if ((temp
= cupsdCopyLocation(po
)) != NULL
)
94 temp
->limit
= CUPSD_AUTH_LIMIT_IPP
;
96 cupsArrayAdd(p
->ops
, temp
);
104 * 'cupsdCheckPolicy()' - Check the IPP operation and username against a policy.
107 http_status_t
/* I - 1 if OK, 0 otherwise */
108 cupsdCheckPolicy(cupsd_policy_t
*p
, /* I - Policy */
109 cupsd_client_t
*con
, /* I - Client connection */
110 const char *owner
) /* I - Owner of object */
112 cupsd_location_t
*po
; /* Current policy operation */
121 cupsdLogMessage(CUPSD_LOG_CRIT
, "cupsdCheckPolicy: p=%p, con=%p.", p
, con
);
123 return ((http_status_t
)0);
127 * Find a match for the operation...
130 if ((po
= cupsdFindPolicyOp(p
, con
->request
->request
.op
.operation_id
)) == NULL
)
132 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdCheckPolicy: No matching operation, returning 0.");
133 return ((http_status_t
)0);
139 * Return the status of the check...
142 return (cupsdIsAuthorized(con
, owner
));
147 * 'cupsdDeleteAllPolicies()' - Delete all policies in memory.
151 cupsdDeleteAllPolicies(void)
153 cupsd_printer_t
*printer
; /* Current printer */
160 * First clear the policy pointers for all printers...
163 for (printer
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
165 printer
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
166 printer
->op_policy_ptr
= NULL
;
168 DefaultPolicyPtr
= NULL
;
171 * Then free all of the policies...
174 cupsArrayDelete(Policies
);
181 * 'cupsdFindPolicy()' - Find a named policy.
184 cupsd_policy_t
* /* O - Policy */
185 cupsdFindPolicy(const char *policy
) /* I - Name of policy */
187 cupsd_policy_t key
; /* Search key */
201 key
.name
= (char *)policy
;
202 return ((cupsd_policy_t
*)cupsArrayFind(Policies
, &key
));
207 * 'cupsdFindPolicyOp()' - Find a policy operation.
210 cupsd_location_t
* /* O - Policy operation */
211 cupsdFindPolicyOp(cupsd_policy_t
*p
, /* I - Policy */
212 ipp_op_t op
) /* I - IPP operation */
214 cupsd_location_t key
, /* Search key... */
215 *po
; /* Current policy operation */
218 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdFindPolicyOp(p=%p, op=%x(%s))",
219 p
, op
, ippOpString(op
));
229 * Check the operation against the available policies...
233 if ((po
= (cupsd_location_t
*)cupsArrayFind(p
->ops
, &key
)) != NULL
)
235 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
236 "cupsdFindPolicyOp: Found exact match...");
240 key
.op
= IPP_ANY_OPERATION
;
241 if ((po
= (cupsd_location_t
*)cupsArrayFind(p
->ops
, &key
)) != NULL
)
243 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
244 "cupsdFindPolicyOp: Found wildcard match...");
248 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdFindPolicyOp: No match found.");
255 * 'cupsdGetPrivateAttrs()' - Get the private attributes for the current
259 cups_array_t
* /* O - Array or NULL for no restrictions */
260 cupsdGetPrivateAttrs(
261 cupsd_policy_t
*policy
, /* I - Policy */
262 cupsd_client_t
*con
, /* I - Client connection */
263 cupsd_printer_t
*printer
, /* I - Printer, if any */
264 const char *owner
) /* I - Owner of object */
266 char *name
; /* Current name in access list */
267 cups_array_t
*access_ptr
, /* Access array */
268 *attrs_ptr
; /* Attributes array */
269 const char *username
; /* Username associated with request */
270 ipp_attribute_t
*attr
; /* Attribute from request */
271 struct passwd
*pw
; /* User info */
275 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
276 "cupsdGetPrivateAttrs(policy=%p(%s), con=%p(%d), "
277 "printer=%p(%s), owner=\"%s\")", policy
, policy
->name
, con
,
278 con
->number
, printer
, printer
? printer
->name
: "", owner
);
283 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
);
284 policy
= DefaultPolicyPtr
;
288 * Get the access and attributes lists that correspond to the request...
292 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: %s",
293 ippOpString(con
->request
->request
.op
.operation_id
));
296 switch (con
->request
->request
.op
.operation_id
)
298 case IPP_GET_SUBSCRIPTIONS
:
299 case IPP_GET_SUBSCRIPTION_ATTRIBUTES
:
300 case IPP_GET_NOTIFICATIONS
:
301 access_ptr
= policy
->sub_access
;
302 attrs_ptr
= policy
->sub_attrs
;
306 access_ptr
= policy
->job_access
;
307 attrs_ptr
= policy
->job_attrs
;
312 * If none of the attributes are private, return NULL now...
315 if ((name
= (char *)cupsArrayFirst(attrs_ptr
)) != NULL
&&
316 !_cups_strcasecmp(name
, "none"))
319 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning NULL.");
326 * Otherwise check the user against the access list...
329 if (con
->username
[0])
330 username
= con
->username
;
331 else if ((attr
= ippFindAttribute(con
->request
, "requesting-user-name",
332 IPP_TAG_NAME
)) != NULL
)
333 username
= attr
->values
[0].string
.text
;
335 username
= "anonymous";
339 pw
= getpwnam(username
);
346 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: username=\"%s\"",
351 * Otherwise check the user against the access list...
354 for (name
= (char *)cupsArrayFirst(access_ptr
);
356 name
= (char *)cupsArrayNext(access_ptr
))
359 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: name=%s", name
);
362 if (printer
&& !_cups_strcasecmp(name
, "@ACL"))
364 char *acl
; /* Current ACL user/group */
366 for (acl
= (char *)cupsArrayFirst(printer
->users
);
368 acl
= (char *)cupsArrayNext(printer
->users
))
373 * Check group membership...
376 if (cupsdCheckGroup(username
, pw
, acl
+ 1))
379 else if (acl
[0] == '#')
385 if (cupsdCheckGroup(username
, pw
, acl
))
388 else if (!_cups_strcasecmp(username
, acl
))
392 else if (owner
&& !_cups_strcasecmp(name
, "@OWNER") &&
393 !_cups_strcasecmp(username
, owner
))
396 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
397 "cupsdGetPrivateAttrs: Returning NULL.");
402 else if (!_cups_strcasecmp(name
, "@SYSTEM"))
404 int i
; /* Looping var */
406 for (i
= 0; i
< NumSystemGroups
; i
++)
407 if (cupsdCheckGroup(username
, pw
, SystemGroups
[i
]))
410 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
411 "cupsdGetPrivateAttrs: Returning NULL.");
417 else if (name
[0] == '@')
419 if (cupsdCheckGroup(username
, pw
, name
+ 1))
422 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
423 "cupsdGetPrivateAttrs: Returning NULL.");
429 else if (!_cups_strcasecmp(username
, name
))
432 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning NULL.");
440 * No direct access, so return private attributes list...
444 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning list.");
452 * 'compare_ops()' - Compare two operations.
455 static int /* O - Result of comparison */
456 compare_ops(cupsd_location_t
*a
, /* I - First operation */
457 cupsd_location_t
*b
) /* I - Second operation */
459 return (a
->op
- b
->op
);
464 * 'compare_policies()' - Compare two policies.
467 static int /* O - Result of comparison */
468 compare_policies(cupsd_policy_t
*a
, /* I - First policy */
469 cupsd_policy_t
*b
) /* I - Second policy */
471 return (_cups_strcasecmp(a
->name
, b
->name
));
476 * 'free_policy()' - Free the memory used by a policy.
480 free_policy(cupsd_policy_t
*p
) /* I - Policy to free */
482 cupsArrayDelete(p
->job_access
);
483 cupsArrayDelete(p
->job_attrs
);
484 cupsArrayDelete(p
->sub_access
);
485 cupsArrayDelete(p
->sub_attrs
);
486 cupsArrayDelete(p
->ops
);
487 cupsdClearString(&p
->name
);
493 * 'hash_op()' - Generate a lookup hash for the operation.
496 static int /* O - Hash value */
497 hash_op(cupsd_location_t
*op
) /* I - Operation */
499 return (((op
->op
>> 6) & 0x40) | (op
->op
& 0x3f));