2 * "$Id: policy.c 11684 2014-03-05 20:01:48Z msweet $"
4 * Policy routines for the CUPS scheduler.
6 * Copyright 2007-2011, 2014 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 * Include necessary headers...
28 static int compare_ops(cupsd_location_t
*a
, cupsd_location_t
*b
);
29 static int compare_policies(cupsd_policy_t
*a
, cupsd_policy_t
*b
);
30 static void free_policy(cupsd_policy_t
*p
);
31 static int hash_op(cupsd_location_t
*op
);
35 * 'cupsdAddPolicy()' - Add a policy to the system.
38 cupsd_policy_t
* /* O - Policy */
39 cupsdAddPolicy(const char *policy
) /* I - Name of policy */
41 cupsd_policy_t
*temp
; /* Pointer to policy */
48 Policies
= cupsArrayNew3((cups_array_func_t
)compare_policies
, NULL
,
49 (cups_ahash_func_t
)NULL
, 0,
50 (cups_acopy_func_t
)NULL
,
51 (cups_afree_func_t
)free_policy
);
56 if ((temp
= calloc(1, sizeof(cupsd_policy_t
))) != NULL
)
58 cupsdSetString(&temp
->name
, policy
);
59 cupsArrayAdd(Policies
, temp
);
67 * 'cupsdAddPolicyOp()' - Add an operation to a policy.
70 cupsd_location_t
* /* O - New policy operation */
71 cupsdAddPolicyOp(cupsd_policy_t
*p
, /* I - Policy */
72 cupsd_location_t
*po
, /* I - Policy operation to copy */
73 ipp_op_t op
) /* I - IPP operation code */
75 cupsd_location_t
*temp
; /* New policy operation */
78 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdAddPolicyOp(p=%p, po=%p, op=%x(%s))",
79 p
, po
, op
, ippOpString(op
));
85 p
->ops
= cupsArrayNew3((cups_array_func_t
)compare_ops
, NULL
,
86 (cups_ahash_func_t
)hash_op
, 128,
87 (cups_acopy_func_t
)NULL
,
88 (cups_afree_func_t
)cupsdFreeLocation
);
93 if ((temp
= cupsdCopyLocation(po
)) != NULL
)
96 temp
->limit
= CUPSD_AUTH_LIMIT_IPP
;
98 cupsArrayAdd(p
->ops
, temp
);
106 * 'cupsdCheckPolicy()' - Check the IPP operation and username against a policy.
109 http_status_t
/* I - 1 if OK, 0 otherwise */
110 cupsdCheckPolicy(cupsd_policy_t
*p
, /* I - Policy */
111 cupsd_client_t
*con
, /* I - Client connection */
112 const char *owner
) /* I - Owner of object */
114 cupsd_location_t
*po
; /* Current policy operation */
123 cupsdLogMessage(CUPSD_LOG_CRIT
, "cupsdCheckPolicy: p=%p, con=%p.", p
, con
);
125 return ((http_status_t
)0);
129 * Find a match for the operation...
132 if ((po
= cupsdFindPolicyOp(p
, con
->request
->request
.op
.operation_id
)) == NULL
)
134 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdCheckPolicy: No matching operation, returning 0.");
135 return ((http_status_t
)0);
141 * Return the status of the check...
144 return (cupsdIsAuthorized(con
, owner
));
149 * 'cupsdDeleteAllPolicies()' - Delete all policies in memory.
153 cupsdDeleteAllPolicies(void)
155 cupsd_printer_t
*printer
; /* Current printer */
162 * First clear the policy pointers for all printers...
165 for (printer
= (cupsd_printer_t
*)cupsArrayFirst(Printers
);
167 printer
= (cupsd_printer_t
*)cupsArrayNext(Printers
))
168 printer
->op_policy_ptr
= NULL
;
170 DefaultPolicyPtr
= NULL
;
173 * Then free all of the policies...
176 cupsArrayDelete(Policies
);
183 * 'cupsdFindPolicy()' - Find a named policy.
186 cupsd_policy_t
* /* O - Policy */
187 cupsdFindPolicy(const char *policy
) /* I - Name of policy */
189 cupsd_policy_t key
; /* Search key */
203 key
.name
= (char *)policy
;
204 return ((cupsd_policy_t
*)cupsArrayFind(Policies
, &key
));
209 * 'cupsdFindPolicyOp()' - Find a policy operation.
212 cupsd_location_t
* /* O - Policy operation */
213 cupsdFindPolicyOp(cupsd_policy_t
*p
, /* I - Policy */
214 ipp_op_t op
) /* I - IPP operation */
216 cupsd_location_t key
, /* Search key... */
217 *po
; /* Current policy operation */
220 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdFindPolicyOp(p=%p, op=%x(%s))",
221 p
, op
, ippOpString(op
));
231 * Check the operation against the available policies...
235 if ((po
= (cupsd_location_t
*)cupsArrayFind(p
->ops
, &key
)) != NULL
)
237 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
238 "cupsdFindPolicyOp: Found exact match...");
242 key
.op
= IPP_ANY_OPERATION
;
243 if ((po
= (cupsd_location_t
*)cupsArrayFind(p
->ops
, &key
)) != NULL
)
245 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
246 "cupsdFindPolicyOp: Found wildcard match...");
250 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdFindPolicyOp: No match found.");
257 * 'cupsdGetPrivateAttrs()' - Get the private attributes for the current
261 cups_array_t
* /* O - Array or NULL for no restrictions */
262 cupsdGetPrivateAttrs(
263 cupsd_policy_t
*policy
, /* I - Policy */
264 cupsd_client_t
*con
, /* I - Client connection */
265 cupsd_printer_t
*printer
, /* I - Printer, if any */
266 const char *owner
) /* I - Owner of object */
268 char *name
; /* Current name in access list */
269 cups_array_t
*access_ptr
, /* Access array */
270 *attrs_ptr
; /* Attributes array */
271 const char *username
; /* Username associated with request */
272 ipp_attribute_t
*attr
; /* Attribute from request */
273 struct passwd
*pw
; /* User info */
277 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
278 "cupsdGetPrivateAttrs(policy=%p(%s), con=%p(%d), "
279 "printer=%p(%s), owner=\"%s\")", policy
, policy
->name
, con
,
280 con
->http
.fd
, printer
, printer
? printer
->name
: "", owner
);
285 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
);
286 policy
= DefaultPolicyPtr
;
290 * Get the access and attributes lists that correspond to the request...
294 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: %s",
295 ippOpString(con
->request
->request
.op
.operation_id
));
298 switch (con
->request
->request
.op
.operation_id
)
300 case IPP_GET_SUBSCRIPTIONS
:
301 case IPP_GET_SUBSCRIPTION_ATTRIBUTES
:
302 case IPP_GET_NOTIFICATIONS
:
303 access_ptr
= policy
->sub_access
;
304 attrs_ptr
= policy
->sub_attrs
;
308 access_ptr
= policy
->job_access
;
309 attrs_ptr
= policy
->job_attrs
;
314 * If none of the attributes are private, return NULL now...
317 if ((name
= (char *)cupsArrayFirst(attrs_ptr
)) != NULL
&&
318 !_cups_strcasecmp(name
, "none"))
321 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning NULL.");
328 * Otherwise check the user against the access list...
331 if (con
->username
[0])
332 username
= con
->username
;
333 else if ((attr
= ippFindAttribute(con
->request
, "requesting-user-name",
334 IPP_TAG_NAME
)) != NULL
)
335 username
= attr
->values
[0].string
.text
;
337 username
= "anonymous";
341 pw
= getpwnam(username
);
348 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: username=\"%s\"",
353 * Otherwise check the user against the access list...
356 for (name
= (char *)cupsArrayFirst(access_ptr
);
358 name
= (char *)cupsArrayNext(access_ptr
))
361 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: name=%s", name
);
364 if (printer
&& !_cups_strcasecmp(name
, "@ACL"))
366 char *acl
; /* Current ACL user/group */
368 for (acl
= (char *)cupsArrayFirst(printer
->users
);
370 acl
= (char *)cupsArrayNext(printer
->users
))
375 * Check group membership...
378 if (cupsdCheckGroup(username
, pw
, acl
+ 1))
381 else if (acl
[0] == '#')
387 if (cupsdCheckGroup(username
, pw
, acl
))
390 else if (!_cups_strcasecmp(username
, acl
))
394 else if (owner
&& !_cups_strcasecmp(name
, "@OWNER") &&
395 !_cups_strcasecmp(username
, owner
))
398 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
399 "cupsdGetPrivateAttrs: Returning NULL.");
404 else if (!_cups_strcasecmp(name
, "@SYSTEM"))
406 int i
; /* Looping var */
408 for (i
= 0; i
< NumSystemGroups
; i
++)
409 if (cupsdCheckGroup(username
, pw
, SystemGroups
[i
]))
412 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
413 "cupsdGetPrivateAttrs: Returning NULL.");
419 else if (name
[0] == '@')
421 if (cupsdCheckGroup(username
, pw
, name
+ 1))
424 cupsdLogMessage(CUPSD_LOG_DEBUG2
,
425 "cupsdGetPrivateAttrs: Returning NULL.");
431 else if (!_cups_strcasecmp(username
, name
))
434 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning NULL.");
442 * No direct access, so return private attributes list...
446 cupsdLogMessage(CUPSD_LOG_DEBUG2
, "cupsdGetPrivateAttrs: Returning list.");
454 * 'compare_ops()' - Compare two operations.
457 static int /* O - Result of comparison */
458 compare_ops(cupsd_location_t
*a
, /* I - First operation */
459 cupsd_location_t
*b
) /* I - Second operation */
461 return (a
->op
- b
->op
);
466 * 'compare_policies()' - Compare two policies.
469 static int /* O - Result of comparison */
470 compare_policies(cupsd_policy_t
*a
, /* I - First policy */
471 cupsd_policy_t
*b
) /* I - Second policy */
473 return (_cups_strcasecmp(a
->name
, b
->name
));
478 * 'free_policy()' - Free the memory used by a policy.
482 free_policy(cupsd_policy_t
*p
) /* I - Policy to free */
484 cupsArrayDelete(p
->job_access
);
485 cupsArrayDelete(p
->job_attrs
);
486 cupsArrayDelete(p
->sub_access
);
487 cupsArrayDelete(p
->sub_attrs
);
488 cupsArrayDelete(p
->ops
);
489 cupsdClearString(&p
->name
);
495 * 'hash_op()' - Generate a lookup hash for the operation.
498 static int /* O - Hash value */
499 hash_op(cupsd_location_t
*op
) /* I - Operation */
501 return (((op
->op
>> 6) & 0x40) | (op
->op
& 0x3f));
506 * End of "$Id: policy.c 11684 2014-03-05 20:01:48Z msweet $".