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