4 * Policy routines for the CUPS scheduler.
6 * Copyright 2007-2011 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * AddPolicy() - Add a policy to the system.
18 * cupsdAddPolicyOp() - Add an operation to a policy.
19 * cupsdCheckPolicy() - Check the IPP operation and username against a
21 * cupsdDeleteAllPolicies() - Delete all policies in memory.
22 * cupsdFindPolicy() - Find a named policy.
23 * cupsdFindPolicyOp() - Find a policy operation.
24 * cupsdGetPrivateAttrs() - Get the private attributes for the current
26 * compare_ops() - Compare two operations.
27 * compare_policies() - Compare two policies.
28 * free_policy() - Free the memory used by a policy.
29 * hash_op() - Generate a lookup hash for the operation.
33 * Include necessary headers...
44 static int compare_ops(cupsd_location_t
*a
, cupsd_location_t
*b
);
45 static int compare_policies(cupsd_policy_t
*a
, cupsd_policy_t
*b
);
46 static void free_policy(cupsd_policy_t
*p
);
47 static int hash_op(cupsd_location_t
*op
);
51 * 'AddPolicy()' - Add a policy to the system.
54 cupsd_policy_t
* /* O - Policy */
55 cupsdAddPolicy(const char *policy
) /* I - Name of policy */
57 cupsd_policy_t
*temp
; /* Pointer to policy */
64 Policies
= cupsArrayNew3((cups_array_func_t
)compare_policies
, NULL
,
65 (cups_ahash_func_t
)NULL
, 0,
66 (cups_acopy_func_t
)NULL
,
67 (cups_afree_func_t
)free_policy
);
72 if ((temp
= calloc(1, sizeof(cupsd_policy_t
))) != NULL
)
74 cupsdSetString(&temp
->name
, policy
);
75 cupsArrayAdd(Policies
, temp
);
83 * 'cupsdAddPolicyOp()' - Add an operation to a policy.
86 cupsd_location_t
* /* O - New policy operation */
87 cupsdAddPolicyOp(cupsd_policy_t
*p
, /* I - Policy */
88 cupsd_location_t
*po
, /* I - Policy operation to copy */
89 ipp_op_t op
) /* I - IPP operation code */
91 cupsd_location_t
*temp
; /* New policy operation */
94 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdAddPolicyOp(p=%p, po=%p, op=%x(%s))",
95 p
, po
, op
, ippOpString(op
));
101 p
->ops
= cupsArrayNew3((cups_array_func_t
)compare_ops
, NULL
,
102 (cups_ahash_func_t
)hash_op
, 128,
103 (cups_acopy_func_t
)NULL
,
104 (cups_afree_func_t
)cupsdFreeLocation
);
109 if ((temp
= cupsdCopyLocation(po
)) != NULL
)
112 temp
->limit
= CUPSD_AUTH_LIMIT_IPP
;
114 cupsArrayAdd(p
->ops
, temp
);
122 * 'cupsdCheckPolicy()' - Check the IPP operation and username against a policy.
125 http_status_t
/* I - 1 if OK, 0 otherwise */
126 cupsdCheckPolicy(cupsd_policy_t
*p
, /* I - Policy */
127 cupsd_client_t
*con
, /* I - Client connection */
128 const char *owner
) /* I - Owner of object */
130 cupsd_location_t
*po
; /* Current policy operation */
139 cupsdLogMessage(CUPSD_LOG_CRIT
, "cupsdCheckPolicy: p=%p, con=%p!", p
, con
);
141 return ((http_status_t
)0);
145 * Find a match for the operation...
148 if ((po
= cupsdFindPolicyOp(p
, con
->request
->request
.op
.operation_id
)) == NULL
)
150 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdCheckPolicy: No matching operation, returning 0!");
151 return ((http_status_t
)0);
157 * Return the status of the check...
160 return (cupsdIsAuthorized(con
, owner
));
165 * 'cupsdDeleteAllPolicies()' - Delete all policies in memory.
169 cupsdDeleteAllPolicies(void)
171 cupsd_printer_t
*printer
; /* Current printer */
178 * First clear the policy pointers for all printers...
181 for (printer
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
183 printer
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
184 printer
->op_policy_ptr
= NULL
;
186 DefaultPolicyPtr
= NULL
;
189 * Then free all of the policies...
192 cupsArrayDelete(Policies
);
199 * 'cupsdFindPolicy()' - Find a named policy.
202 cupsd_policy_t
* /* O - Policy */
203 cupsdFindPolicy(const char *policy
) /* I - Name of policy */
205 cupsd_policy_t key
; /* Search key */
219 key
.name
= (char *)policy
;
220 return ((cupsd_policy_t
*)cupsArrayFind(Policies
, &key
));
225 * 'cupsdFindPolicyOp()' - Find a policy operation.
228 cupsd_location_t
* /* O - Policy operation */
229 cupsdFindPolicyOp(cupsd_policy_t
*p
, /* I - Policy */
230 ipp_op_t op
) /* I - IPP operation */
232 cupsd_location_t key
, /* Search key... */
233 *po
; /* Current policy operation */
236 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdFindPolicyOp(p=%p, op=%x(%s))",
237 p
, op
, ippOpString(op
));
247 * Check the operation against the available policies...
251 if ((po
= (cupsd_location_t
*)cupsArrayFind(p
->ops
, &key
)) != NULL
)
253 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
254 "cupsdFindPolicyOp: Found exact match...");
258 key
.op
= IPP_ANY_OPERATION
;
259 if ((po
= (cupsd_location_t
*)cupsArrayFind(p
->ops
, &key
)) != NULL
)
261 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
262 "cupsdFindPolicyOp: Found wildcard match...");
266 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdFindPolicyOp: No match found!");
273 * 'cupsdGetPrivateAttrs()' - Get the private attributes for the current
277 cups_array_t
* /* O - Array or NULL for no restrictions */
278 cupsdGetPrivateAttrs(
279 cupsd_policy_t
*policy
, /* I - Policy */
280 cupsd_client_t
*con
, /* I - Client connection */
281 cupsd_printer_t
*printer
, /* I - Printer, if any */
282 const char *owner
) /* I - Owner of object */
284 char *name
; /* Current name in access list */
285 cups_array_t
*access_ptr
, /* Access array */
286 *attrs_ptr
; /* Attributes array */
287 const char *username
; /* Username associated with request */
288 ipp_attribute_t
*attr
; /* Attribute from request */
289 struct passwd
*pw
; /* User info */
293 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
294 "cupsdGetPrivateAttrs(policy=%p(%s), con=%p(%d), "
295 "printer=%p(%s), owner=\"%s\")", policy
, policy
->name
, con
,
296 con
->http
.fd
, printer
, printer
? printer
->name
: "", owner
);
300 * Get the access and attributes lists that correspond to the request...
304 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: %s",
305 ippOpString(con
->request
->request
.op
.operation_id
));
308 switch (con
->request
->request
.op
.operation_id
)
310 case IPP_GET_SUBSCRIPTIONS
:
311 case IPP_GET_SUBSCRIPTION_ATTRIBUTES
:
312 case IPP_GET_NOTIFICATIONS
:
313 access_ptr
= policy
->sub_access
;
314 attrs_ptr
= policy
->sub_attrs
;
318 access_ptr
= policy
->job_access
;
319 attrs_ptr
= policy
->job_attrs
;
324 * If none of the attributes are private, return NULL now...
327 if ((name
= (char *)cupsArrayFirst(attrs_ptr
)) != NULL
&&
328 !_cups_strcasecmp(name
, "none"))
331 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning NULL.");
338 * Otherwise check the user against the access list...
341 if (con
->username
[0])
342 username
= con
->username
;
343 else if ((attr
= ippFindAttribute(con
->request
, "requesting-user-name",
344 IPP_TAG_NAME
)) != NULL
)
345 username
= attr
->values
[0].string
.text
;
347 username
= "anonymous";
351 pw
= getpwnam(username
);
358 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: username=\"%s\"",
363 * Otherwise check the user against the access list...
366 for (name
= (char *)cupsArrayFirst(access_ptr
);
368 name
= (char *)cupsArrayNext(access_ptr
))
371 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: name=%s", name
);
374 if (printer
&& !_cups_strcasecmp(name
, "@ACL"))
376 char *acl
; /* Current ACL user/group */
378 for (acl
= (char *)cupsArrayFirst(printer
->users
);
380 acl
= (char *)cupsArrayNext(printer
->users
))
385 * Check group membership...
388 if (cupsdCheckGroup(username
, pw
, acl
+ 1))
391 else if (acl
[0] == '#')
397 if (cupsdCheckGroup(username
, pw
, acl
))
400 else if (!_cups_strcasecmp(username
, acl
))
404 else if (owner
&& !_cups_strcasecmp(name
, "@OWNER") &&
405 !_cups_strcasecmp(username
, owner
))
408 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
409 "cupsdGetPrivateAttrs: Returning NULL.");
414 else if (!_cups_strcasecmp(name
, "@SYSTEM"))
416 int i
; /* Looping var */
418 for (i
= 0; i
< NumSystemGroups
; i
++)
419 if (cupsdCheckGroup(username
, pw
, SystemGroups
[i
]))
422 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
423 "cupsdGetPrivateAttrs: Returning NULL.");
429 else if (name
[0] == '@')
431 if (cupsdCheckGroup(username
, pw
, name
+ 1))
434 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
435 "cupsdGetPrivateAttrs: Returning NULL.");
441 else if (!_cups_strcasecmp(username
, name
))
444 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning NULL.");
452 * No direct access, so return private attributes list...
456 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning list.");
464 * 'compare_ops()' - Compare two operations.
467 static int /* O - Result of comparison */
468 compare_ops(cupsd_location_t
*a
, /* I - First operation */
469 cupsd_location_t
*b
) /* I - Second operation */
471 return (a
->op
- b
->op
);
476 * 'compare_policies()' - Compare two policies.
479 static int /* O - Result of comparison */
480 compare_policies(cupsd_policy_t
*a
, /* I - First policy */
481 cupsd_policy_t
*b
) /* I - Second policy */
483 return (_cups_strcasecmp(a
->name
, b
->name
));
488 * 'free_policy()' - Free the memory used by a policy.
492 free_policy(cupsd_policy_t
*p
) /* I - Policy to free */
494 cupsArrayDelete(p
->job_access
);
495 cupsArrayDelete(p
->job_attrs
);
496 cupsArrayDelete(p
->sub_access
);
497 cupsArrayDelete(p
->sub_attrs
);
498 cupsArrayDelete(p
->ops
);
499 cupsdClearString(&p
->name
);
505 * 'hash_op()' - Generate a lookup hash for the operation.
508 static int /* O - Hash value */
509 hash_op(cupsd_location_t
*op
) /* I - Operation */
511 return (((op
->op
>> 6) & 0x40) | (op
->op
& 0x3f));