]> git.ipfire.org Git - thirdparty/cups.git/blame - scheduler/policy.c
Ignore empty STATE: messages.
[thirdparty/cups.git] / scheduler / policy.c
CommitLineData
f27bd5ab 1/*
c9d3f842 2 * "$Id$"
f27bd5ab 3 *
64252c8e 4 * Policy routines for the CUPS scheduler.
f27bd5ab 5 *
c6fab96f 6 * Copyright 2007-2011 by Apple Inc.
dfd3d12a 7 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
f27bd5ab 8 *
9 * These coded instructions, statements, and computer programs are the
4e8d321f 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/".
f27bd5ab 14 *
15 * Contents:
16 *
392a9cf1 17 * AddPolicy() - Add a policy to the system.
99baf768 18 * cupsdAddPolicyOp() - Add an operation to a policy.
392a9cf1 19 * cupsdCheckPolicy() - Check the IPP operation and username against a
20 * policy.
99baf768 21 * cupsdDeleteAllPolicies() - Delete all policies in memory.
22 * cupsdFindPolicy() - Find a named policy.
23 * cupsdFindPolicyOp() - Find a policy operation.
392a9cf1 24 * cupsdGetPrivateAttrs() - Get the private attributes for the current
25 * request.
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.
f27bd5ab 30 */
31
32/*
33 * Include necessary headers...
34 */
35
36#include "cupsd.h"
392a9cf1 37#include <pwd.h>
53ca8055 38
f27bd5ab 39
71d7e94c 40/*
41 * Local functions...
42 */
43
44static int compare_ops(cupsd_location_t *a, cupsd_location_t *b);
45static int compare_policies(cupsd_policy_t *a, cupsd_policy_t *b);
96336986 46static void free_policy(cupsd_policy_t *p);
71d7e94c 47static int hash_op(cupsd_location_t *op);
48
49
f27bd5ab 50/*
51 * 'AddPolicy()' - Add a policy to the system.
52 */
53
99baf768 54cupsd_policy_t * /* O - Policy */
55cupsdAddPolicy(const char *policy) /* I - Name of policy */
f27bd5ab 56{
71d7e94c 57 cupsd_policy_t *temp; /* Pointer to policy */
53ca8055 58
59
71d7e94c 60 if (!policy)
53ca8055 61 return (NULL);
62
71d7e94c 63 if (!Policies)
96336986 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);
53ca8055 68
71d7e94c 69 if (!Policies)
4b6bdd9f 70 return (NULL);
71
99baf768 72 if ((temp = calloc(1, sizeof(cupsd_policy_t))) != NULL)
53ca8055 73 {
71d7e94c 74 cupsdSetString(&temp->name, policy);
75 cupsArrayAdd(Policies, temp);
53ca8055 76 }
77
78 return (temp);
f27bd5ab 79}
80
81
82/*
99baf768 83 * 'cupsdAddPolicyOp()' - Add an operation to a policy.
f27bd5ab 84 */
85
f3e786fc 86cupsd_location_t * /* O - New policy operation */
87cupsdAddPolicyOp(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 */
f27bd5ab 90{
71d7e94c 91 cupsd_location_t *temp; /* New policy operation */
53ca8055 92
93
f3e786fc 94 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdAddPolicyOp(p=%p, po=%p, op=%x(%s))",
95 p, po, op, ippOpString(op));
0051f336 96
71d7e94c 97 if (!p)
53ca8055 98 return (NULL);
99
71d7e94c 100 if (!p->ops)
96336986 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);
53ca8055 105
71d7e94c 106 if (!p->ops)
4b6bdd9f 107 return (NULL);
108
96336986 109 if ((temp = cupsdCopyLocation(po)) != NULL)
53ca8055 110 {
99baf768 111 temp->op = op;
7ed0bc61 112 temp->limit = CUPSD_AUTH_LIMIT_IPP;
4b6bdd9f 113
71d7e94c 114 cupsArrayAdd(p->ops, temp);
53ca8055 115 }
116
117 return (temp);
f27bd5ab 118}
119
120
121/*
99baf768 122 * 'cupsdCheckPolicy()' - Check the IPP operation and username against a policy.
f27bd5ab 123 */
124
5df46530 125http_status_t /* I - 1 if OK, 0 otherwise */
99baf768 126cupsdCheckPolicy(cupsd_policy_t *p, /* I - Policy */
f3e786fc 127 cupsd_client_t *con, /* I - Client connection */
99baf768 128 const char *owner) /* I - Owner of object */
f27bd5ab 129{
f3e786fc 130 cupsd_location_t *po; /* Current policy operation */
53ca8055 131
132
133 /*
134 * Range check...
135 */
136
bd5510a5 137 if (!p || !con)
fd09381d 138 {
f3e786fc 139 cupsdLogMessage(CUPSD_LOG_CRIT, "cupsdCheckPolicy: p=%p, con=%p!", p, con);
fd09381d 140
be5262d8 141 return ((http_status_t)0);
fd09381d 142 }
53ca8055 143
144 /*
4b6bdd9f 145 * Find a match for the operation...
53ca8055 146 */
147
0051f336 148 if ((po = cupsdFindPolicyOp(p, con->request->request.op.operation_id)) == NULL)
5934328c 149 {
f3e786fc 150 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCheckPolicy: No matching operation, returning 0!");
be5262d8 151 return ((http_status_t)0);
5934328c 152 }
4b6bdd9f 153
f32b1ead 154 con->best = po;
53ca8055 155
156 /*
4b6bdd9f 157 * Return the status of the check...
53ca8055 158 */
159
5df46530 160 return (cupsdIsAuthorized(con, owner));
f27bd5ab 161}
162
163
164/*
99baf768 165 * 'cupsdDeleteAllPolicies()' - Delete all policies in memory.
f27bd5ab 166 */
167
168void
99baf768 169cupsdDeleteAllPolicies(void)
f27bd5ab 170{
715a3e88 171 cupsd_printer_t *printer; /* Current printer */
53ca8055 172
173
71d7e94c 174 if (!Policies)
53ca8055 175 return;
176
715a3e88 177 /*
178 * First clear the policy pointers for all printers...
179 */
180
181 for (printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
182 printer;
183 printer = (cupsd_printer_t *)cupsArrayNext(Printers))
184 printer->op_policy_ptr = NULL;
185
96336986 186 DefaultPolicyPtr = NULL;
187
715a3e88 188 /*
189 * Then free all of the policies...
190 */
191
71d7e94c 192 cupsArrayDelete(Policies);
53ca8055 193
71d7e94c 194 Policies = NULL;
f27bd5ab 195}
196
197
198/*
99baf768 199 * 'cupsdFindPolicy()' - Find a named policy.
f27bd5ab 200 */
201
99baf768 202cupsd_policy_t * /* O - Policy */
203cupsdFindPolicy(const char *policy) /* I - Name of policy */
f27bd5ab 204{
71d7e94c 205 cupsd_policy_t key; /* Search key */
53ca8055 206
207
208 /*
209 * Range check...
210 */
211
71d7e94c 212 if (!policy)
53ca8055 213 return (NULL);
214
215 /*
71d7e94c 216 * Look it up...
53ca8055 217 */
218
71d7e94c 219 key.name = (char *)policy;
220 return ((cupsd_policy_t *)cupsArrayFind(Policies, &key));
f27bd5ab 221}
222
223
224/*
99baf768 225 * 'cupsdFindPolicyOp()' - Find a policy operation.
f27bd5ab 226 */
227
f3e786fc 228cupsd_location_t * /* O - Policy operation */
99baf768 229cupsdFindPolicyOp(cupsd_policy_t *p, /* I - Policy */
230 ipp_op_t op) /* I - IPP operation */
f27bd5ab 231{
71d7e94c 232 cupsd_location_t key, /* Search key... */
233 *po; /* Current policy operation */
53ca8055 234
235
1ff176b0 236 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp(p=%p, op=%x(%s))",
f3e786fc 237 p, op, ippOpString(op));
a8c7842b 238
53ca8055 239 /*
240 * Range check...
241 */
242
71d7e94c 243 if (!p)
53ca8055 244 return (NULL);
245
246 /*
247 * Check the operation against the available policies...
248 */
249
71d7e94c 250 key.op = op;
251 if ((po = (cupsd_location_t *)cupsArrayFind(p->ops, &key)) != NULL)
252 {
253 cupsdLogMessage(CUPSD_LOG_DEBUG2,
254 "cupsdFindPolicyOp: Found exact match...");
255 return (po);
256 }
4b6bdd9f 257
71d7e94c 258 key.op = IPP_ANY_OPERATION;
259 if ((po = (cupsd_location_t *)cupsArrayFind(p->ops, &key)) != NULL)
260 {
261 cupsdLogMessage(CUPSD_LOG_DEBUG2,
262 "cupsdFindPolicyOp: Found wildcard match...");
263 return (po);
264 }
a8c7842b 265
f3e786fc 266 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFindPolicyOp: No match found!");
53ca8055 267
268 return (NULL);
269}
270
271
392a9cf1 272/*
273 * 'cupsdGetPrivateAttrs()' - Get the private attributes for the current
274 * request.
275 */
276
277cups_array_t * /* O - Array or NULL for no restrictions */
278cupsdGetPrivateAttrs(
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 */
283{
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 */
290
291
292#ifdef DEBUG
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);
297#endif /* DEBUG */
298
299 /*
300 * Get the access and attributes lists that correspond to the request...
301 */
302
303#ifdef DEBUG
304 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: %s",
305 ippOpString(con->request->request.op.operation_id));
306#endif /* DEBUG */
307
308 switch (con->request->request.op.operation_id)
309 {
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;
315 break;
316
317 default :
318 access_ptr = policy->job_access;
319 attrs_ptr = policy->job_attrs;
320 break;
321 }
322
323 /*
324 * If none of the attributes are private, return NULL now...
325 */
326
327 if ((name = (char *)cupsArrayFirst(attrs_ptr)) != NULL &&
c6fab96f 328 !_cups_strcasecmp(name, "none"))
392a9cf1 329 {
330#ifdef DEBUG
331 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning NULL.");
332#endif /* DEBUG */
333
334 return (NULL);
335 }
336
337 /*
338 * Otherwise check the user against the access list...
339 */
340
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;
346 else
347 username = "anonymous";
348
349 if (username[0])
350 {
351 pw = getpwnam(username);
352 endpwent();
353 }
354 else
355 pw = NULL;
356
357#ifdef DEBUG
358 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: username=\"%s\"",
359 username);
360#endif /* DEBUG */
361
362 /*
363 * Otherwise check the user against the access list...
364 */
365
366 for (name = (char *)cupsArrayFirst(access_ptr);
367 name;
368 name = (char *)cupsArrayNext(access_ptr))
369 {
370#ifdef DEBUG
371 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: name=%s", name);
372#endif /* DEBUG */
373
c6fab96f 374 if (printer && !_cups_strcasecmp(name, "@ACL"))
392a9cf1 375 {
376 char *acl; /* Current ACL user/group */
377
378 for (acl = (char *)cupsArrayFirst(printer->users);
379 acl;
380 acl = (char *)cupsArrayNext(printer->users))
381 {
382 if (acl[0] == '@')
383 {
384 /*
385 * Check group membership...
386 */
387
388 if (cupsdCheckGroup(username, pw, acl + 1))
389 break;
390 }
391 else if (acl[0] == '#')
392 {
393 /*
394 * Check UUID...
395 */
396
397 if (cupsdCheckGroup(username, pw, acl))
398 break;
399 }
c6fab96f 400 else if (!_cups_strcasecmp(username, acl))
392a9cf1 401 break;
402 }
403 }
c6fab96f 404 else if (owner && !_cups_strcasecmp(name, "@OWNER") &&
405 !_cups_strcasecmp(username, owner))
392a9cf1 406 {
407#ifdef DEBUG
408 cupsdLogMessage(CUPSD_LOG_DEBUG2,
409 "cupsdGetPrivateAttrs: Returning NULL.");
410#endif /* DEBUG */
411
412 return (NULL);
413 }
c6fab96f 414 else if (!_cups_strcasecmp(name, "@SYSTEM"))
392a9cf1 415 {
416 int i; /* Looping var */
417
418 for (i = 0; i < NumSystemGroups; i ++)
419 if (cupsdCheckGroup(username, pw, SystemGroups[i]))
420 {
421#ifdef DEBUG
422 cupsdLogMessage(CUPSD_LOG_DEBUG2,
423 "cupsdGetPrivateAttrs: Returning NULL.");
424#endif /* DEBUG */
425
426 return (NULL);
427 }
428 }
429 else if (name[0] == '@')
430 {
431 if (cupsdCheckGroup(username, pw, name + 1))
432 {
433#ifdef DEBUG
434 cupsdLogMessage(CUPSD_LOG_DEBUG2,
435 "cupsdGetPrivateAttrs: Returning NULL.");
436#endif /* DEBUG */
437
438 return (NULL);
439 }
440 }
c6fab96f 441 else if (!_cups_strcasecmp(username, name))
392a9cf1 442 {
443#ifdef DEBUG
444 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning NULL.");
445#endif /* DEBUG */
446
447 return (NULL);
448 }
449 }
450
451 /*
452 * No direct access, so return private attributes list...
453 */
454
455#ifdef DEBUG
456 cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning list.");
457#endif /* DEBUG */
458
459 return (attrs_ptr);
460}
461
462
71d7e94c 463/*
464 * 'compare_ops()' - Compare two operations.
465 */
466
467static int /* O - Result of comparison */
468compare_ops(cupsd_location_t *a, /* I - First operation */
469 cupsd_location_t *b) /* I - Second operation */
470{
471 return (a->op - b->op);
472}
473
474
475/*
476 * 'compare_policies()' - Compare two policies.
477 */
478
479static int /* O - Result of comparison */
480compare_policies(cupsd_policy_t *a, /* I - First policy */
481 cupsd_policy_t *b) /* I - Second policy */
482{
c6fab96f 483 return (_cups_strcasecmp(a->name, b->name));
71d7e94c 484}
485
486
96336986 487/*
488 * 'free_policy()' - Free the memory used by a policy.
489 */
490
491static void
492free_policy(cupsd_policy_t *p) /* I - Policy to free */
493{
392a9cf1 494 cupsArrayDelete(p->job_access);
495 cupsArrayDelete(p->job_attrs);
496 cupsArrayDelete(p->sub_access);
497 cupsArrayDelete(p->sub_attrs);
96336986 498 cupsArrayDelete(p->ops);
499 cupsdClearString(&p->name);
500 free(p);
501}
502
503
71d7e94c 504/*
505 * 'hash_op()' - Generate a lookup hash for the operation.
506 */
507
508static int /* O - Hash value */
509hash_op(cupsd_location_t *op) /* I - Operation */
510{
511 return (((op->op >> 6) & 0x40) | (op->op & 0x3f));
512}
513
514
4b6bdd9f 515/*
c9d3f842 516 * End of "$Id$".
f27bd5ab 517 */