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