]> git.ipfire.org Git - thirdparty/cups.git/blob - scheduler/policy.c
Update copyright notices, addresses, etc.
[thirdparty/cups.git] / scheduler / policy.c
1 /*
2 * "$Id$"
3 *
4 * Policy routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * Contents:
25 *
26 */
27
28 /*
29 * Include necessary headers...
30 */
31
32 #include "cupsd.h"
33 #include <pwd.h>
34 #include <grp.h>
35 #ifdef HAVE_USERSEC_H
36 # include <usersec.h>
37 #endif /* HAVE_USERSEC_H */
38
39
40 /*
41 * Local functions...
42 */
43
44 static int check_group(const char *name, const char *group);
45 static int check_op(policyop_t *po, int allow_deny, const char *name,
46 const char *owner);
47
48
49 /*
50 * 'AddPolicy()' - Add a policy to the system.
51 */
52
53 policy_t * /* O - Policy */
54 AddPolicy(const char *policy) /* I - Name of policy */
55 {
56 policy_t *temp, /* Pointer to policy */
57 **tempa; /* Pointer to policy array */
58
59
60 if (policy == NULL)
61 return (NULL);
62
63 if (NumPolicies == 0)
64 tempa = malloc(sizeof(policy_t *));
65 else
66 tempa = realloc(Policies, sizeof(policy_t *) * (NumPolicies + 1));
67
68 if (tempa == NULL)
69 return (NULL);
70
71 Policies = tempa;
72 tempa += NumPolicies;
73
74 if ((temp = calloc(1, sizeof(policy_t))) != NULL)
75 {
76 temp->name = strdup(policy);
77 *tempa = temp;
78
79 NumPolicies ++;
80 }
81
82 return (temp);
83 }
84
85
86 /*
87 * 'AddPolicyOp()' - Add an operation to a policy.
88 */
89
90 policyop_t * /* O - New policy operation */
91 AddPolicyOp(policy_t *p, /* I - Policy */
92 policyop_t *po, /* I - Policy operation to copy */
93 ipp_op_t op) /* I - IPP operation code */
94 {
95 int i; /* Looping var */
96 policyop_t *temp, /* New policy operation */
97 **tempa; /* New policy operation array */
98
99
100 if (p == NULL)
101 return (NULL);
102
103 if (p->num_ops == 0)
104 tempa = malloc(sizeof(policyop_t *));
105 else
106 tempa = realloc(p->ops, sizeof(policyop_t *) * (p->num_ops + 1));
107
108 if (tempa == NULL)
109 return (NULL);
110
111 p->ops = tempa;
112
113 if ((temp = calloc(1, sizeof(policyop_t))) != NULL)
114 {
115 p->ops = tempa;
116 tempa[p->num_ops] = temp;
117 p->num_ops ++;
118
119 temp->op = op;
120
121 if (po)
122 {
123 /*
124 * Copy the specified policy to the new one...
125 */
126
127 temp->order_type = po->order_type;
128 temp->authenticate = po->authenticate;
129 for (i = 0; i < po->num_names; i ++)
130 AddPolicyOpName(temp, po->names[i].allow_deny, po->names[i].name);
131 }
132 }
133
134 return (temp);
135 }
136
137
138 /*
139 * 'AddPolicyOpName()' - Add a name to a policy operation.
140 */
141
142 void
143 AddPolicyOpName(policyop_t *po, /* I - Policy operation */
144 int allow_deny, /* I - POLICY_ALLOW or POLICY_DENY */
145 const char *name) /* I - Name to add */
146 {
147 policyname_t *temp; /* New name array */
148
149
150 if (po == NULL || name == NULL)
151 return;
152
153 if (po->num_names == 0)
154 temp = malloc(sizeof(policyname_t));
155 else
156 temp = realloc(po->names, sizeof(policyname_t) * (po->num_names + 1));
157
158 if (temp != NULL)
159 {
160 po->names = temp;
161 temp += po->num_names;
162 po->num_names ++;
163
164 temp->allow_deny = allow_deny;
165 temp->name = strdup(name);
166 }
167 }
168
169
170 /*
171 * 'CheckPolicy()' - Check the IPP operation and username against a policy.
172 */
173
174 int /* I - 1 if OK, 0 otherwise */
175 CheckPolicy(policy_t *p, /* I - Policy */
176 client_t *con, /* I - Client connection */
177 const char *owner) /* I - Owner of object */
178 {
179 ipp_op_t op; /* IPP operation */
180 const char *name; /* Username */
181 int authenticated; /* Authenticated? */
182 ipp_attribute_t *attr; /* IPP attribute */
183 int status; /* Status */
184 policyop_t *po; /* Current policy operation */
185
186
187 /*
188 * Range check...
189 */
190
191 if (!p || !con)
192 {
193 LogMessage(L_CRIT, "CheckPolicy: p=%p, con=%p!", p, con);
194
195 return (0);
196 }
197
198 /*
199 * Collect info from the request...
200 */
201
202 op = con->request->request.op.operation_id;
203
204 if (con->username[0])
205 {
206 name = con->username;
207 authenticated = 1;
208 }
209 else if ((attr = ippFindAttribute(con->request, "requesting-user-name",
210 IPP_TAG_NAME)) != NULL)
211 {
212 name = attr->values[0].string.text;
213 authenticated = 0;
214 }
215 else
216 {
217 name = "anonymous";
218 authenticated = 0;
219 }
220
221 LogMessage(L_DEBUG2, "CheckPolicy: op=%04x, name=\"%s\", authenticated=%d, owner=\"%s\"",
222 op, name, authenticated, owner ? owner : "");
223
224 /*
225 * Find a match for the operation...
226 */
227
228 if ((po = FindPolicyOp(p, op)) == NULL)
229 {
230 LogMessage(L_DEBUG2, "CheckPolicy: No matching operation, returning 0!");
231 return (0);
232 }
233
234 /*
235 * Check the policy against the current user, etc.
236 */
237
238 if (po->authenticate && !authenticated)
239 {
240 LogMessage(L_DEBUG2, "CheckPolicy: Operation requires authentication, returning 0!");
241 return (0);
242 }
243
244 switch (status = po->order_type)
245 {
246 default :
247 case POLICY_ALLOW :
248 if (check_op(po, POLICY_DENY, name, owner))
249 status = POLICY_DENY;
250 if (check_op(po, POLICY_ALLOW, name, owner))
251 status = POLICY_ALLOW;
252 break;
253
254 case POLICY_DENY :
255 if (check_op(po, POLICY_ALLOW, name, owner))
256 status = POLICY_ALLOW;
257 if (check_op(po, POLICY_DENY, name, owner))
258 status = POLICY_DENY;
259 break;
260 }
261
262 /*
263 * Return the status of the check...
264 */
265
266 LogMessage(L_DEBUG2, "CheckPolicy: Returning %d...", !status);
267
268 return (!status);
269 }
270
271
272 /*
273 * 'DeleteAllPolicies()' - Delete all policies in memory.
274 */
275
276 void
277 DeleteAllPolicies(void)
278 {
279 int i, j, k; /* Looping vars */
280 policy_t **p; /* Current policy */
281 policyop_t **po; /* Current policy operation */
282 policyname_t *pn; /* Current policy name */
283
284
285 if (NumPolicies == 0)
286 return;
287
288 for (i = NumPolicies, p = Policies; i > 0; i --, p ++)
289 {
290 for (j = (*p)->num_ops, po = (*p)->ops; j > 0; j --, po ++)
291 {
292 for (k = (*po)->num_names, pn = (*po)->names; k > 0; k --, pn ++)
293 free(pn->name);
294
295 if ((*po)->num_names > 0)
296 free((*po)->names);
297
298 free(*po);
299 }
300
301 if ((*p)->num_ops > 0)
302 free((*p)->ops);
303
304 free(*p);
305 }
306
307 free(Policies);
308
309 NumPolicies = 0;
310 Policies = NULL;
311 }
312
313
314 /*
315 * 'FindPolicy()' - Find a named policy.
316 */
317
318 policy_t * /* O - Policy */
319 FindPolicy(const char *policy) /* I - Name of policy */
320 {
321 int i; /* Looping var */
322 policy_t **p; /* Current policy */
323
324
325 /*
326 * Range check...
327 */
328
329 if (policy == NULL)
330 return (NULL);
331
332 /*
333 * Check the operation against the available policies...
334 */
335
336 for (i = NumPolicies, p = Policies; i > 0; i --, p ++)
337 if (strcasecmp(policy, (*p)->name) == 0)
338 return (*p);
339
340 return (NULL);
341 }
342
343
344 /*
345 * 'FindPolicyOp()' - Find a policy operation.
346 */
347
348 policyop_t * /* O - Policy operation */
349 FindPolicyOp(policy_t *p, /* I - Policy */
350 ipp_op_t op) /* I - IPP operation */
351 {
352 int i; /* Looping var */
353 policyop_t **po; /* Current policy operation */
354
355
356 /*
357 * Range check...
358 */
359
360 if (p == NULL)
361 return (NULL);
362
363 /*
364 * Check the operation against the available policies...
365 */
366
367 for (i = p->num_ops, po = p->ops; i > 0; i --, po ++)
368 if ((*po)->op == op)
369 return (*po);
370
371 for (i = p->num_ops, po = p->ops; i > 0; i --, po ++)
372 if ((*po)->op == IPP_ANY_OPERATION)
373 return (*po);
374
375 return (NULL);
376 }
377
378
379 /*
380 * 'validate_user()' - Validate the user for the request.
381 */
382
383 static int /* O - 1 if permitted, 0 otherwise */
384 check_group(const char *username, /* I - Authenticated username */
385 const char *groupname) /* I - Group name */
386 {
387 int i; /* Looping var */
388 struct passwd *user; /* User info */
389 struct group *group; /* System group info */
390 char junk[33]; /* MD5 password (not used) */
391
392
393 LogMessage(L_DEBUG2, "check_group(%s, %s)\n", username, groupname);
394
395 /*
396 * Validate input...
397 */
398
399 if (username == NULL || groupname == NULL)
400 return (0);
401
402 /*
403 * Check to see if the user is a member of the named group...
404 */
405
406 user = getpwnam(username);
407 endpwent();
408
409 group = getgrnam(groupname);
410 endgrent();
411
412 if (group != NULL)
413 {
414 /*
415 * Group exists, check it...
416 */
417
418 for (i = 0; group->gr_mem[i]; i ++)
419 if (strcasecmp(username, group->gr_mem[i]) == 0)
420 return (1);
421 }
422
423 /*
424 * Group doesn't exist or user not in group list, check the group ID
425 * against the user's group ID...
426 */
427
428 if (user != NULL && group != NULL && group->gr_gid == user->pw_gid)
429 return (1);
430
431 /*
432 * Username not found, group not found, or user is not part of the
433 * system group... Check for a user and group in the MD5 password
434 * file...
435 */
436
437 if (GetMD5Passwd(username, groupname, junk) != NULL)
438 return (1);
439
440 /*
441 * If we get this far, then the user isn't part of the named group...
442 */
443
444 return (0);
445
446
447 #if 0 //// OLD OLD OLD OLD OLD
448 if (strcasecmp(username, owner) != 0 && strcasecmp(username, "root") != 0)
449 {
450 /*
451 * Not the owner or root; check to see if the user is a member of the
452 * system group...
453 */
454
455 user = getpwnam(username);
456 endpwent();
457
458 for (i = 0, j = 0, group = NULL; i < NumSystemGroups; i ++)
459 {
460 group = getgrnam(SystemGroups[i]);
461 endgrent();
462
463 if (group != NULL)
464 {
465 for (j = 0; group->gr_mem[j]; j ++)
466 if (strcasecmp(username, group->gr_mem[j]) == 0)
467 break;
468
469 if (group->gr_mem[j])
470 break;
471 }
472 else
473 j = 0;
474 }
475
476 if (user == NULL || group == NULL ||
477 (group->gr_mem[j] == NULL && group->gr_gid != user->pw_gid))
478 {
479 /*
480 * Username not found, group not found, or user is not part of the
481 * system group... Check for a user and group in the MD5 password
482 * file...
483 */
484
485 for (i = 0; i < NumSystemGroups; i ++)
486 if (GetMD5Passwd(username, SystemGroups[i], junk) != NULL)
487 return (1);
488
489 /*
490 * Nope, not an MD5 user, either. Return 0 indicating no-go...
491 */
492
493 return (0);
494 }
495 }
496
497 return (1);
498 #endif //// 0
499 }
500
501
502 /*
503 * 'check_op()' - Check the current operation.
504 */
505
506 static int /* O - 1 if match, 0 if not */
507 check_op(policyop_t *po, /* I - Policy operation */
508 int allow_deny, /* I - POLICY_ALLOW or POLICY_DENY */
509 const char *name, /* I - User name */
510 const char *owner) /* I - Owner name */
511 {
512 int i; /* Looping vars */
513 policyname_t *pn; /* Current policy name */
514
515
516 for (i = po->num_names, pn = po->names; i > 0; i --, pn ++)
517 {
518 if (pn->allow_deny != allow_deny)
519 continue;
520
521 if (!strcasecmp(pn->name, "@OWNER"))
522 {
523 if (owner && !strcasecmp(name, owner))
524 return (1);
525 }
526 else if (pn->name[0] == '@')
527 {
528 if (check_group(name, pn->name + 1))
529 return (1);
530 }
531 else if (!strcasecmp(name, pn->name))
532 return (1);
533 }
534
535 return (0);
536 }
537
538
539 /*
540 * End of "$Id$".
541 */