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