]>
Commit | Line | Data |
---|---|---|
f27bd5ab | 1 | /* |
c9d3f842 | 2 | * "$Id$" |
f27bd5ab | 3 | * |
4 | * Policy routines for the Common UNIX Printing System (CUPS). | |
5 | * | |
c9d3f842 | 6 | * Copyright 1997-2005 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 | |
c9d3f842 | 18 | * Hollywood, Maryland 20636 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" | |
f27bd5ab | 33 | #include <grp.h> |
34 | #ifdef HAVE_USERSEC_H | |
35 | # include <usersec.h> | |
36 | #endif /* HAVE_USERSEC_H */ | |
37 | ||
38 | ||
39 | /* | |
40 | * Local functions... | |
41 | */ | |
42 | ||
4b6bdd9f | 43 | static int check_op(policyop_t *po, int allow_deny, const char *name, |
44 | const char *owner); | |
53ca8055 | 45 | |
f27bd5ab | 46 | |
47 | /* | |
48 | * 'AddPolicy()' - Add a policy to the system. | |
49 | */ | |
50 | ||
51 | policy_t * /* O - Policy */ | |
52 | AddPolicy(const char *policy) /* I - Name of policy */ | |
53 | { | |
4b6bdd9f | 54 | policy_t *temp, /* Pointer to policy */ |
55 | **tempa; /* Pointer to policy array */ | |
53ca8055 | 56 | |
57 | ||
58 | if (policy == NULL) | |
59 | return (NULL); | |
60 | ||
61 | if (NumPolicies == 0) | |
4b6bdd9f | 62 | tempa = malloc(sizeof(policy_t *)); |
53ca8055 | 63 | else |
4b6bdd9f | 64 | tempa = realloc(Policies, sizeof(policy_t *) * (NumPolicies + 1)); |
53ca8055 | 65 | |
4b6bdd9f | 66 | if (tempa == NULL) |
67 | return (NULL); | |
68 | ||
69 | Policies = tempa; | |
70 | tempa += NumPolicies; | |
71 | ||
72 | if ((temp = calloc(1, sizeof(policy_t))) != NULL) | |
53ca8055 | 73 | { |
4b6bdd9f | 74 | temp->name = strdup(policy); |
75 | *tempa = temp; | |
53ca8055 | 76 | |
4b6bdd9f | 77 | NumPolicies ++; |
53ca8055 | 78 | } |
79 | ||
80 | return (temp); | |
f27bd5ab | 81 | } |
82 | ||
83 | ||
84 | /* | |
85 | * 'AddPolicyOp()' - Add an operation to a policy. | |
86 | */ | |
87 | ||
88 | policyop_t * /* O - New policy operation */ | |
4b6bdd9f | 89 | AddPolicyOp(policy_t *p, /* I - Policy */ |
90 | policyop_t *po, /* I - Policy operation to copy */ | |
91 | ipp_op_t op) /* I - IPP operation code */ | |
f27bd5ab | 92 | { |
4b6bdd9f | 93 | int i; /* Looping var */ |
94 | policyop_t *temp, /* New policy operation */ | |
95 | **tempa; /* New policy operation array */ | |
53ca8055 | 96 | |
97 | ||
98 | if (p == NULL) | |
99 | return (NULL); | |
100 | ||
101 | if (p->num_ops == 0) | |
4b6bdd9f | 102 | tempa = malloc(sizeof(policyop_t *)); |
53ca8055 | 103 | else |
4b6bdd9f | 104 | tempa = realloc(p->ops, sizeof(policyop_t *) * (p->num_ops + 1)); |
53ca8055 | 105 | |
4b6bdd9f | 106 | if (tempa == NULL) |
107 | return (NULL); | |
108 | ||
109 | p->ops = tempa; | |
110 | ||
111 | if ((temp = calloc(1, sizeof(policyop_t))) != NULL) | |
53ca8055 | 112 | { |
4b6bdd9f | 113 | p->ops = tempa; |
114 | tempa[p->num_ops] = temp; | |
53ca8055 | 115 | p->num_ops ++; |
116 | ||
53ca8055 | 117 | temp->op = op; |
4b6bdd9f | 118 | |
119 | if (po) | |
120 | { | |
121 | /* | |
122 | * Copy the specified policy to the new one... | |
123 | */ | |
124 | ||
125 | temp->order_type = po->order_type; | |
126 | temp->authenticate = po->authenticate; | |
127 | for (i = 0; i < po->num_names; i ++) | |
128 | AddPolicyOpName(temp, po->names[i].allow_deny, po->names[i].name); | |
129 | } | |
53ca8055 | 130 | } |
131 | ||
132 | return (temp); | |
f27bd5ab | 133 | } |
134 | ||
135 | ||
136 | /* | |
137 | * 'AddPolicyOpName()' - Add a name to a policy operation. | |
138 | */ | |
139 | ||
140 | void | |
141 | AddPolicyOpName(policyop_t *po, /* I - Policy operation */ | |
4b6bdd9f | 142 | int allow_deny, /* I - POLICY_ALLOW or POLICY_DENY */ |
f27bd5ab | 143 | const char *name) /* I - Name to add */ |
144 | { | |
4b6bdd9f | 145 | policyname_t *temp; /* New name array */ |
53ca8055 | 146 | |
147 | ||
148 | if (po == NULL || name == NULL) | |
149 | return; | |
150 | ||
151 | if (po->num_names == 0) | |
4b6bdd9f | 152 | temp = malloc(sizeof(policyname_t)); |
53ca8055 | 153 | else |
4b6bdd9f | 154 | temp = realloc(po->names, sizeof(policyname_t) * (po->num_names + 1)); |
53ca8055 | 155 | |
156 | if (temp != NULL) | |
157 | { | |
158 | po->names = temp; | |
159 | temp += po->num_names; | |
160 | po->num_names ++; | |
161 | ||
4b6bdd9f | 162 | temp->allow_deny = allow_deny; |
163 | temp->name = strdup(name); | |
53ca8055 | 164 | } |
f27bd5ab | 165 | } |
166 | ||
167 | ||
168 | /* | |
169 | * 'CheckPolicy()' - Check the IPP operation and username against a policy. | |
170 | */ | |
171 | ||
172 | int /* I - 1 if OK, 0 otherwise */ | |
173 | CheckPolicy(policy_t *p, /* I - Policy */ | |
bd5510a5 | 174 | client_t *con, /* I - Client connection */ |
53ca8055 | 175 | const char *owner) /* I - Owner of object */ |
f27bd5ab | 176 | { |
bd5510a5 | 177 | ipp_op_t op; /* IPP operation */ |
178 | const char *name; /* Username */ | |
179 | int authenticated; /* Authenticated? */ | |
180 | ipp_attribute_t *attr; /* IPP attribute */ | |
4b6bdd9f | 181 | int status; /* Status */ |
53ca8055 | 182 | policyop_t *po; /* Current policy operation */ |
53ca8055 | 183 | |
184 | ||
185 | /* | |
186 | * Range check... | |
187 | */ | |
188 | ||
bd5510a5 | 189 | if (!p || !con) |
fd09381d | 190 | { |
191 | LogMessage(L_CRIT, "CheckPolicy: p=%p, con=%p!", p, con); | |
192 | ||
53ca8055 | 193 | return (0); |
fd09381d | 194 | } |
53ca8055 | 195 | |
bd5510a5 | 196 | /* |
197 | * Collect info from the request... | |
198 | */ | |
199 | ||
200 | op = con->request->request.op.operation_id; | |
201 | ||
202 | if (con->username[0]) | |
203 | { | |
204 | name = con->username; | |
205 | authenticated = 1; | |
206 | } | |
207 | else if ((attr = ippFindAttribute(con->request, "requesting-user-name", | |
208 | IPP_TAG_NAME)) != NULL) | |
209 | { | |
210 | name = attr->values[0].string.text; | |
211 | authenticated = 0; | |
212 | } | |
213 | else | |
214 | { | |
215 | name = "anonymous"; | |
216 | authenticated = 0; | |
217 | } | |
218 | ||
5934328c | 219 | LogMessage(L_DEBUG2, "CheckPolicy: op=%04x, name=\"%s\", authenticated=%d, owner=\"%s\"", |
220 | op, name, authenticated, owner ? owner : ""); | |
221 | ||
53ca8055 | 222 | /* |
4b6bdd9f | 223 | * Find a match for the operation... |
53ca8055 | 224 | */ |
225 | ||
4b6bdd9f | 226 | if ((po = FindPolicyOp(p, op)) == NULL) |
5934328c | 227 | { |
228 | LogMessage(L_DEBUG2, "CheckPolicy: No matching operation, returning 0!"); | |
4b6bdd9f | 229 | return (0); |
5934328c | 230 | } |
4b6bdd9f | 231 | |
232 | /* | |
233 | * Check the policy against the current user, etc. | |
234 | */ | |
235 | ||
236 | if (po->authenticate && !authenticated) | |
5934328c | 237 | { |
238 | LogMessage(L_DEBUG2, "CheckPolicy: Operation requires authentication, returning 0!"); | |
4b6bdd9f | 239 | return (0); |
5934328c | 240 | } |
4b6bdd9f | 241 | |
242 | switch (status = po->order_type) | |
243 | { | |
244 | default : | |
245 | case POLICY_ALLOW : | |
246 | if (check_op(po, POLICY_DENY, name, owner)) | |
247 | status = POLICY_DENY; | |
248 | if (check_op(po, POLICY_ALLOW, name, owner)) | |
249 | status = POLICY_ALLOW; | |
250 | break; | |
251 | ||
252 | case POLICY_DENY : | |
253 | if (check_op(po, POLICY_ALLOW, name, owner)) | |
254 | status = POLICY_ALLOW; | |
255 | if (check_op(po, POLICY_DENY, name, owner)) | |
256 | status = POLICY_DENY; | |
257 | break; | |
258 | } | |
53ca8055 | 259 | |
260 | /* | |
4b6bdd9f | 261 | * Return the status of the check... |
53ca8055 | 262 | */ |
263 | ||
5934328c | 264 | LogMessage(L_DEBUG2, "CheckPolicy: Returning %d...", !status); |
265 | ||
4b6bdd9f | 266 | return (!status); |
f27bd5ab | 267 | } |
268 | ||
269 | ||
270 | /* | |
271 | * 'DeleteAllPolicies()' - Delete all policies in memory. | |
272 | */ | |
273 | ||
274 | void | |
275 | DeleteAllPolicies(void) | |
276 | { | |
4b6bdd9f | 277 | int i, j, k; /* Looping vars */ |
278 | policy_t **p; /* Current policy */ | |
279 | policyop_t **po; /* Current policy operation */ | |
280 | policyname_t *pn; /* Current policy name */ | |
53ca8055 | 281 | |
282 | ||
283 | if (NumPolicies == 0) | |
284 | return; | |
285 | ||
286 | for (i = NumPolicies, p = Policies; i > 0; i --, p ++) | |
287 | { | |
4b6bdd9f | 288 | for (j = (*p)->num_ops, po = (*p)->ops; j > 0; j --, po ++) |
53ca8055 | 289 | { |
4b6bdd9f | 290 | for (k = (*po)->num_names, pn = (*po)->names; k > 0; k --, pn ++) |
291 | free(pn->name); | |
292 | ||
293 | if ((*po)->num_names > 0) | |
294 | free((*po)->names); | |
53ca8055 | 295 | |
4b6bdd9f | 296 | free(*po); |
53ca8055 | 297 | } |
298 | ||
4b6bdd9f | 299 | if ((*p)->num_ops > 0) |
300 | free((*p)->ops); | |
301 | ||
302 | free(*p); | |
53ca8055 | 303 | } |
304 | ||
305 | free(Policies); | |
306 | ||
307 | NumPolicies = 0; | |
308 | Policies = NULL; | |
f27bd5ab | 309 | } |
310 | ||
311 | ||
312 | /* | |
313 | * 'FindPolicy()' - Find a named policy. | |
314 | */ | |
315 | ||
316 | policy_t * /* O - Policy */ | |
317 | FindPolicy(const char *policy) /* I - Name of policy */ | |
318 | { | |
53ca8055 | 319 | int i; /* Looping var */ |
4b6bdd9f | 320 | policy_t **p; /* Current policy */ |
53ca8055 | 321 | |
322 | ||
323 | /* | |
324 | * Range check... | |
325 | */ | |
326 | ||
327 | if (policy == NULL) | |
328 | return (NULL); | |
329 | ||
330 | /* | |
331 | * Check the operation against the available policies... | |
332 | */ | |
333 | ||
334 | for (i = NumPolicies, p = Policies; i > 0; i --, p ++) | |
4b6bdd9f | 335 | if (strcasecmp(policy, (*p)->name) == 0) |
336 | return (*p); | |
53ca8055 | 337 | |
338 | return (NULL); | |
f27bd5ab | 339 | } |
340 | ||
341 | ||
342 | /* | |
343 | * 'FindPolicyOp()' - Find a policy operation. | |
344 | */ | |
345 | ||
346 | policyop_t * /* O - Policy operation */ | |
347 | FindPolicyOp(policy_t *p, /* I - Policy */ | |
348 | ipp_op_t op) /* I - IPP operation */ | |
349 | { | |
53ca8055 | 350 | int i; /* Looping var */ |
4b6bdd9f | 351 | policyop_t **po; /* Current policy operation */ |
53ca8055 | 352 | |
353 | ||
354 | /* | |
355 | * Range check... | |
356 | */ | |
357 | ||
358 | if (p == NULL) | |
359 | return (NULL); | |
360 | ||
361 | /* | |
362 | * Check the operation against the available policies... | |
363 | */ | |
364 | ||
365 | for (i = p->num_ops, po = p->ops; i > 0; i --, po ++) | |
4b6bdd9f | 366 | if ((*po)->op == op) |
367 | return (*po); | |
368 | ||
369 | for (i = p->num_ops, po = p->ops; i > 0; i --, po ++) | |
370 | if ((*po)->op == IPP_ANY_OPERATION) | |
371 | return (*po); | |
53ca8055 | 372 | |
373 | return (NULL); | |
374 | } | |
375 | ||
376 | ||
f27bd5ab | 377 | /* |
4b6bdd9f | 378 | * 'check_op()' - Check the current operation. |
379 | */ | |
380 | ||
381 | static int /* O - 1 if match, 0 if not */ | |
382 | check_op(policyop_t *po, /* I - Policy operation */ | |
383 | int allow_deny, /* I - POLICY_ALLOW or POLICY_DENY */ | |
384 | const char *name, /* I - User name */ | |
385 | const char *owner) /* I - Owner name */ | |
386 | { | |
9d0c9f28 | 387 | int i, j; /* Looping vars */ |
4b6bdd9f | 388 | policyname_t *pn; /* Current policy name */ |
9d0c9f28 | 389 | struct passwd *pw; /* User's password entry */ |
4b6bdd9f | 390 | |
391 | ||
9d0c9f28 | 392 | pw = getpwnam(name); |
393 | endpwent(); | |
394 | ||
4b6bdd9f | 395 | for (i = po->num_names, pn = po->names; i > 0; i --, pn ++) |
396 | { | |
397 | if (pn->allow_deny != allow_deny) | |
398 | continue; | |
399 | ||
400 | if (!strcasecmp(pn->name, "@OWNER")) | |
401 | { | |
402 | if (owner && !strcasecmp(name, owner)) | |
403 | return (1); | |
404 | } | |
9d0c9f28 | 405 | else if (!strcasecmp(pn->name, "@SYSTEM")) |
406 | { | |
407 | for (j = 0; j < NumSystemGroups; j ++) | |
408 | if (cupsdCheckGroup(name, pw, SystemGroups[j])) | |
409 | return (1); | |
410 | } | |
4b6bdd9f | 411 | else if (pn->name[0] == '@') |
412 | { | |
9d0c9f28 | 413 | if (cupsdCheckGroup(name, pw, pn->name + 1)) |
4b6bdd9f | 414 | return (1); |
415 | } | |
416 | else if (!strcasecmp(name, pn->name)) | |
417 | return (1); | |
418 | } | |
419 | ||
420 | return (0); | |
421 | } | |
422 | ||
423 | ||
424 | /* | |
c9d3f842 | 425 | * End of "$Id$". |
f27bd5ab | 426 | */ |