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