]>
Commit | Line | Data |
---|---|---|
1 | /* $Id$ | |
2 | * | |
3 | * Check access to queries | |
4 | * | |
5 | * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology | |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
8 | */ | |
9 | ||
10 | #include <mit-copyright.h> | |
11 | #include "mr_server.h" | |
12 | #include "qrtn.h" | |
13 | #include "query.h" | |
14 | ||
15 | #include <ctype.h> | |
16 | #include <stdlib.h> | |
17 | ||
18 | EXEC SQL INCLUDE sqlca; | |
19 | ||
20 | RCSID("$Header$"); | |
21 | ||
22 | extern char *whoami; | |
23 | extern int dbms_errno, mr_errcode; | |
24 | ||
25 | EXEC SQL WHENEVER SQLERROR DO dbmserr(); | |
26 | ||
27 | ||
28 | /* Specialized Access Routines */ | |
29 | ||
30 | /* access_user - verify that client name equals specified login name | |
31 | * | |
32 | * - since field validation routines are called first, a users_id is | |
33 | * now in argv[0] instead of the login name. | |
34 | */ | |
35 | ||
36 | int access_user(struct query *q, char *argv[], client *cl) | |
37 | { | |
38 | if (cl->users_id != *(int *)argv[0]) | |
39 | return MR_PERM; | |
40 | else | |
41 | return MR_SUCCESS; | |
42 | } | |
43 | ||
44 | ||
45 | ||
46 | /* access_login - verify that client name equals specified login name | |
47 | * | |
48 | * argv[0...n] contain search info. q-> | |
49 | */ | |
50 | ||
51 | int access_login(struct query *q, char *argv[], client *cl) | |
52 | { | |
53 | EXEC SQL BEGIN DECLARE SECTION; | |
54 | int id; | |
55 | EXEC SQL END DECLARE SECTION; | |
56 | ||
57 | if (q->argc != 1) | |
58 | return MR_ARGS; | |
59 | ||
60 | if (!strcmp(q->shortname, "gual")) | |
61 | { | |
62 | EXEC SQL SELECT users_id INTO :id FROM users | |
63 | WHERE login = :argv[0] AND users_id != 0; | |
64 | } | |
65 | else if (!strcmp(q->shortname, "gubl")) | |
66 | { | |
67 | EXEC SQL SELECT users_id INTO :id FROM users u | |
68 | WHERE u.login = :argv[0] AND u.users_id != 0; | |
69 | } | |
70 | else if (!strcmp(q->shortname, "guau")) | |
71 | { | |
72 | EXEC SQL SELECT users_id INTO :id FROM users | |
73 | WHERE unix_uid = :argv[0] AND users_id != 0; | |
74 | } | |
75 | else if (!strcmp(q->shortname, "gubu")) | |
76 | { | |
77 | EXEC SQL SELECT users_id INTO :id FROM users u | |
78 | WHERE u.unix_uid = :argv[0] AND u.users_id != 0; | |
79 | } | |
80 | ||
81 | if (sqlca.sqlcode == SQL_NO_MATCH) | |
82 | return MR_NO_MATCH; /* ought to be MR_USER, but this is what | |
83 | gual returns, so we have to be consistent */ | |
84 | else if (sqlca.sqlerrd[2] != 1 || id != cl->users_id) | |
85 | return MR_PERM; | |
86 | else | |
87 | return MR_SUCCESS; | |
88 | } | |
89 | ||
90 | ||
91 | /* access_spob - check access for set_pobox */ | |
92 | ||
93 | int access_spob(struct query *q, char *argv[], client *cl) | |
94 | { | |
95 | EXEC SQL BEGIN DECLARE SECTION; | |
96 | int id; | |
97 | EXEC SQL END DECLARE SECTION; | |
98 | ||
99 | if (!strcmp(argv[1], "IMAP")) | |
100 | { | |
101 | EXEC SQL SELECT owner INTO :id FROM filesys f | |
102 | WHERE f.label = :argv[2] AND f.type = 'IMAP' AND | |
103 | f.lockertype = 'USER'; | |
104 | if (cl->users_id != id) | |
105 | return MR_PERM; | |
106 | } | |
107 | if (cl->users_id != *(int *)argv[0]) | |
108 | return MR_PERM; | |
109 | else | |
110 | return MR_SUCCESS; | |
111 | } | |
112 | ||
113 | ||
114 | /* access_list - check access for most list operations | |
115 | * | |
116 | * Inputs: argv[0] - list_id | |
117 | * q - query name | |
118 | * argv[2] - member ID (only for queries "amtl" and "dmfl") | |
119 | * argv[7] - group ID (only for query "ulis") | |
120 | * cl - client name | |
121 | * | |
122 | * - check that client is a member of the access control list | |
123 | * - OR, if the query is add_member_to_list or delete_member_from_list | |
124 | * and the list is public, allow access if client = member | |
125 | */ | |
126 | ||
127 | int access_list(struct query *q, char *argv[], client *cl) | |
128 | { | |
129 | EXEC SQL BEGIN DECLARE SECTION; | |
130 | int list_id, acl_id, flags, gid, users_id, member_id, member_acl_id; | |
131 | int memacl_id; | |
132 | char acl_type[LIST_ACL_TYPE_SIZE], name[LIST_NAME_SIZE], *newname; | |
133 | char member_acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; | |
134 | EXEC SQL END DECLARE SECTION; | |
135 | int status; | |
136 | ||
137 | list_id = *(int *)argv[0]; | |
138 | member_id = *(int *)argv[2]; | |
139 | EXEC SQL SELECT acl_id, acl_type, memacl_id, memacl_type, | |
140 | gid, publicflg, name | |
141 | INTO :acl_id, :acl_type, :memacl_id, :memacl_type, | |
142 | :gid, :flags, :name | |
143 | FROM list | |
144 | WHERE list_id = :list_id; | |
145 | ||
146 | if (sqlca.sqlerrd[2] != 1) | |
147 | return MR_INTERNAL; | |
148 | ||
149 | /* if update_list, don't allow them to change the GID or rename to a | |
150 | username other than their own */ | |
151 | if (!strcmp("ulis", q->shortname)) | |
152 | { | |
153 | if (!strcmp(argv[7], UNIQUE_GID)) | |
154 | { | |
155 | if (gid != -1) | |
156 | return MR_PERM; | |
157 | } | |
158 | else | |
159 | { | |
160 | if (gid != atoi(argv[7])) | |
161 | return MR_PERM; | |
162 | } | |
163 | ||
164 | newname = argv[1]; | |
165 | ||
166 | if (!strcmp("ulis", q->shortname)) | |
167 | { | |
168 | /* Check that it doesn't conflict with the Grouper namespace. */ | |
169 | if (strlen(newname) > 4 && isdigit(newname[2]) && | |
170 | isdigit(newname[3]) && newname[4] == '-') | |
171 | { | |
172 | if (!strncasecmp(newname, "fa", 2) || | |
173 | !strncasecmp(newname, "sp", 2) || | |
174 | !strncasecmp(newname, "su", 2) || | |
175 | !strncasecmp(newname, "ja", 2)) | |
176 | return MR_RESERVED; | |
177 | } | |
178 | ||
179 | /* Don't let anyone take owner-foo list names. They interact | |
180 | * weirdly with the aliases automatically generated by | |
181 | * mailhub.gen. | |
182 | */ | |
183 | if (!strncasecmp(newname, "owner-", 6)) | |
184 | return MR_RESERVED; | |
185 | } | |
186 | ||
187 | EXEC SQL SELECT users_id INTO :users_id FROM users | |
188 | WHERE login = :newname; | |
189 | if ((sqlca.sqlcode != SQL_NO_MATCH) && strcmp(strtrim(name), newname) && | |
190 | (users_id != cl->users_id)) | |
191 | return MR_PERM; | |
192 | } | |
193 | ||
194 | /* check for client in access control list and return success right | |
195 | * away if it's there. */ | |
196 | if (find_member(acl_type, acl_id, cl)) | |
197 | return MR_SUCCESS; | |
198 | ||
199 | /* If not amtl, atml, or dmfl, we lose. */ | |
200 | if (strcmp(q->shortname, "amtl") && strcmp(q->shortname, "atml") && | |
201 | strcmp(q->shortname, "dmfl") && strcmp(q->shortname, "tmol")) | |
202 | return MR_PERM; | |
203 | ||
204 | if (find_member(memacl_type, memacl_id, cl)) | |
205 | return MR_SUCCESS; | |
206 | ||
207 | if (flags || q->type == DELETE) | |
208 | { | |
209 | if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id) | |
210 | return MR_SUCCESS; | |
211 | if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id) | |
212 | return MR_SUCCESS; | |
213 | if (!strcmp("LIST", argv[1]) && !strcmp("dmfl", q->shortname)) | |
214 | { | |
215 | EXEC SQL SELECT acl_id, acl_type INTO :member_acl_id, | |
216 | :member_acl_type | |
217 | FROM list | |
218 | WHERE list_id = :member_id; | |
219 | ||
220 | if (find_member(member_acl_type, member_acl_id, cl)) | |
221 | return MR_SUCCESS; | |
222 | } | |
223 | } | |
224 | ||
225 | /* Otherwise fail. */ | |
226 | return MR_PERM; | |
227 | } | |
228 | ||
229 | ||
230 | /* access_visible_list - allow access to list only if it is not hidden, | |
231 | * or if the client is on the ACL | |
232 | * | |
233 | * Inputs: argv[0] - list_id | |
234 | * cl - client identifier | |
235 | */ | |
236 | ||
237 | int access_visible_list(struct query *q, char *argv[], client *cl) | |
238 | { | |
239 | EXEC SQL BEGIN DECLARE SECTION; | |
240 | int list_id, acl_id, memacl_id, flags ; | |
241 | char acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; | |
242 | EXEC SQL END DECLARE SECTION; | |
243 | int status; | |
244 | ||
245 | list_id = *(int *)argv[0]; | |
246 | EXEC SQL SELECT hidden, acl_id, acl_type, memacl_id, memacl_type | |
247 | INTO :flags, :acl_id, :acl_type, :memacl_id, :memacl_type | |
248 | FROM list | |
249 | WHERE list_id = :list_id; | |
250 | if (sqlca.sqlerrd[2] != 1) | |
251 | return MR_INTERNAL; | |
252 | if (!flags) | |
253 | return MR_SUCCESS; | |
254 | ||
255 | /* check for client in access control list */ | |
256 | status = find_member(acl_type, acl_id, cl); | |
257 | if (!status) | |
258 | { | |
259 | status = find_member(memacl_type, memacl_id, cl); | |
260 | if (!status) | |
261 | return MR_PERM; | |
262 | } | |
263 | return MR_SUCCESS; | |
264 | } | |
265 | ||
266 | ||
267 | /* access_vis_list_by_name - allow access to list only if it is not hidden, | |
268 | * or if the client is on the ACL | |
269 | * | |
270 | * Inputs: argv[0] - list name | |
271 | * cl - client identifier | |
272 | */ | |
273 | ||
274 | int access_vis_list_by_name(struct query *q, char *argv[], client *cl) | |
275 | { | |
276 | EXEC SQL BEGIN DECLARE SECTION; | |
277 | int acl_id, memacl_id, flags, rowcount; | |
278 | char acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; | |
279 | char *listname; | |
280 | EXEC SQL END DECLARE SECTION; | |
281 | int status; | |
282 | ||
283 | listname = argv[0]; | |
284 | EXEC SQL SELECT hidden, acl_id, acl_type, memacl_id, memacl_type | |
285 | INTO :flags, :acl_id, :acl_type, :memacl_id, :memacl_type | |
286 | FROM list | |
287 | WHERE name = :listname; | |
288 | ||
289 | rowcount = sqlca.sqlerrd[2]; | |
290 | if (rowcount > 1) | |
291 | return MR_WILDCARD; | |
292 | if (rowcount == 0) | |
293 | return MR_NO_MATCH; | |
294 | if (!flags) | |
295 | return MR_SUCCESS; | |
296 | ||
297 | /* check for client in access control list */ | |
298 | status = find_member(acl_type, acl_id, cl); | |
299 | if (!status) | |
300 | { | |
301 | status = find_member(memacl_type, memacl_id, cl); | |
302 | if (!status) | |
303 | return MR_PERM; | |
304 | } | |
305 | return MR_SUCCESS; | |
306 | } | |
307 | ||
308 | ||
309 | /* access_member - allow user to access member of type "USER" and name matches | |
310 | * username, or to access member of type "KERBEROS" and the principal matches | |
311 | * the user, or to access member of type "LIST" and list is one that user is | |
312 | * on the acl of, or the list is visible. | |
313 | */ | |
314 | ||
315 | int access_member(struct query *q, char *argv[], client *cl) | |
316 | { | |
317 | if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST")) | |
318 | return access_visible_list(q, &argv[1], cl); | |
319 | ||
320 | if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) | |
321 | { | |
322 | if (cl->users_id == *(int *)argv[1]) | |
323 | return MR_SUCCESS; | |
324 | } | |
325 | ||
326 | if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS")) | |
327 | { | |
328 | if (cl->client_id == -*(int *)argv[1]) | |
329 | return MR_SUCCESS; | |
330 | } | |
331 | ||
332 | return MR_PERM; | |
333 | } | |
334 | ||
335 | ||
336 | /* access_qgli - special access routine for Qualified_get_lists. Allows | |
337 | * access iff argv[0] == "TRUE" and argv[2] == "FALSE". | |
338 | */ | |
339 | ||
340 | int access_qgli(struct query *q, char *argv[], client *cl) | |
341 | { | |
342 | if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE")) | |
343 | return MR_SUCCESS; | |
344 | return MR_PERM; | |
345 | } | |
346 | ||
347 | ||
348 | /* access_service - allow access if user is on ACL of service. Don't | |
349 | * allow access if a wildcard is used. | |
350 | */ | |
351 | ||
352 | int access_service(struct query *q, char *argv[], client *cl) | |
353 | { | |
354 | EXEC SQL BEGIN DECLARE SECTION; | |
355 | int acl_id; | |
356 | char *name, acl_type[LIST_ACL_TYPE_SIZE]; | |
357 | EXEC SQL END DECLARE SECTION; | |
358 | int status; | |
359 | char *c; | |
360 | ||
361 | name = argv[0]; | |
362 | for (c = name; *c; c++) | |
363 | { | |
364 | if (islower(*c)) | |
365 | *c = toupper(*c); | |
366 | } | |
367 | EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers | |
368 | WHERE name = :name; | |
369 | if (sqlca.sqlerrd[2] > 1) | |
370 | return MR_PERM; | |
371 | ||
372 | /* check for client in access control list */ | |
373 | status = find_member(acl_type, acl_id, cl); | |
374 | if (!status) | |
375 | return MR_PERM; | |
376 | ||
377 | return MR_SUCCESS; | |
378 | } | |
379 | ||
380 | ||
381 | /* access_filesys - verify that client is owner or on owners list of filesystem | |
382 | * named by argv[0] | |
383 | */ | |
384 | ||
385 | int access_filesys(struct query *q, char *argv[], client *cl) | |
386 | { | |
387 | EXEC SQL BEGIN DECLARE SECTION; | |
388 | int users_id, list_id; | |
389 | char *name; | |
390 | EXEC SQL END DECLARE SECTION; | |
391 | int status; | |
392 | ||
393 | name = argv[0]; | |
394 | EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys | |
395 | WHERE label = :name; | |
396 | ||
397 | if (sqlca.sqlerrd[2] != 1) | |
398 | return MR_PERM; | |
399 | if (users_id == cl->users_id) | |
400 | return MR_SUCCESS; | |
401 | status = find_member("LIST", list_id, cl); | |
402 | if (status) | |
403 | return MR_SUCCESS; | |
404 | else | |
405 | return MR_PERM; | |
406 | } | |
407 | ||
408 | ||
409 | /* access_host - successful if owner of host, or subnet containing host | |
410 | */ | |
411 | ||
412 | int access_host(struct query *q, char *argv[], client *cl) | |
413 | { | |
414 | EXEC SQL BEGIN DECLARE SECTION; | |
415 | int mid, sid, id, subnet_status; | |
416 | char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE]; | |
417 | char *account_number; | |
418 | EXEC SQL END DECLARE SECTION; | |
419 | int status, idx; | |
420 | ||
421 | if (q->version < 6) | |
422 | idx = 0; | |
423 | else if (q->version >= 6 && q->version < 8) | |
424 | idx = 1; | |
425 | else | |
426 | idx = 2; | |
427 | ||
428 | if (q->type == RETRIEVE) | |
429 | { | |
430 | if (strcmp(argv[0], "*") || strcmp(argv[1], "*") || | |
431 | strcmp(argv[2], "*") || strcmp(argv[3], "*")) | |
432 | return MR_SUCCESS; | |
433 | else | |
434 | return MR_PERM; | |
435 | } | |
436 | ||
437 | if (q->type == APPEND) | |
438 | { | |
439 | /* Non-query owner must set use to zero */ | |
440 | if (atoi(argv[6 + idx]) != 0) | |
441 | return MR_PERM; | |
442 | ||
443 | /* ... and start the hostname with a letter */ | |
444 | if (isdigit(argv[0][0])) | |
445 | return MR_BAD_CHAR; | |
446 | ||
447 | id = *(int *)argv[8 + idx]; | |
448 | EXEC SQL SELECT s.owner_type, s.owner_id, s.status | |
449 | INTO :stype, :sid, :subnet_status FROM subnet s | |
450 | WHERE s.snet_id = :id; | |
451 | mid = 0; | |
452 | ||
453 | /* Non query owner must provide valid billing information. */ | |
454 | if (q->version >= 8) | |
455 | { | |
456 | if (subnet_status == SNET_STATUS_BILLABLE) | |
457 | { | |
458 | account_number = argv[7]; | |
459 | EXEC SQL SELECT account_number FROM accountnumbers | |
460 | WHERE account_number = :account_number; | |
461 | if (sqlca.sqlcode == SQL_NO_MATCH) | |
462 | return MR_ACCOUNT_NUMBER; | |
463 | } | |
464 | } | |
465 | ||
466 | if (find_member(stype, sid, cl)) | |
467 | return MR_SUCCESS; | |
468 | else | |
469 | return MR_PERM; | |
470 | } | |
471 | else /* q-type == UPDATE */ | |
472 | { | |
473 | EXEC SQL BEGIN DECLARE SECTION; | |
474 | int status, acomment, use, ocomment, snid; | |
475 | char contact[MACHINE_CONTACT_SIZE], address[MACHINE_ADDRESS_SIZE]; | |
476 | char name[MACHINE_NAME_SIZE]; | |
477 | char billing_contact[MACHINE_BILLING_CONTACT_SIZE]; | |
478 | EXEC SQL END DECLARE SECTION; | |
479 | ||
480 | id = *(int *)argv[0]; | |
481 | EXEC SQL SELECT m.name, m.use, m.contact, m.billing_contact, m.status, | |
482 | m.address, m.owner_type, m.owner_id, m.acomment, m.ocomment, m.snet_id, | |
483 | s.owner_type, s.owner_id, s.status INTO :name, :use, :contact, | |
484 | :billing_contact, :status, :address, :mtype, :mid, :acomment, | |
485 | :ocomment, :snid, :stype, :sid, :subnet_status | |
486 | FROM machine m, subnet s | |
487 | WHERE m.mach_id = :id AND s.snet_id = m.snet_id; | |
488 | if (dbms_errno) | |
489 | return mr_errcode; | |
490 | ||
491 | /* Non query owner must provide valid billing information. */ | |
492 | if (q->version >= 8) | |
493 | { | |
494 | if (subnet_status == SNET_STATUS_BILLABLE) | |
495 | { | |
496 | account_number = argv[8]; | |
497 | EXEC SQL SELECT account_number FROM accountnumbers | |
498 | WHERE account_number = :account_number; | |
499 | if (sqlca.sqlcode == SQL_NO_MATCH) | |
500 | return MR_ACCOUNT_NUMBER; | |
501 | } | |
502 | } | |
503 | ||
504 | /* non-query-owner cannot change use or ocomment */ | |
505 | if ((use != atoi(argv[7 + idx])) || (ocomment != *(int *)argv[14 + idx])) | |
506 | return MR_PERM; | |
507 | ||
508 | /* or rename to start with digit */ | |
509 | if (isdigit(argv[1][0]) && strcmp(strtrim(name), argv[1])) | |
510 | return MR_BAD_CHAR; | |
511 | ||
512 | if (!find_member(stype, sid, cl)) | |
513 | { | |
514 | if (find_member(mtype, mid, cl)) | |
515 | { | |
516 | /* host owner also cannot change contact, status, address, | |
517 | owner, or acomment */ | |
518 | if (strcmp(argv[6], strtrim(contact)) || | |
519 | (status != atoi(argv[8 + idx])) || | |
520 | strcmp(argv[10 + idx], strtrim(address)) || | |
521 | strcmp(argv[11 + idx], strtrim(mtype)) || | |
522 | (mid != *(int *)argv[12 + idx]) || | |
523 | (acomment != *(int *)argv[13 + idx])) | |
524 | return MR_PERM; | |
525 | /* Billing contact field didn't appear until version 6 */ | |
526 | if (q->version >= 6) | |
527 | if (strcmp(argv[7], strtrim(billing_contact))) | |
528 | return MR_PERM; | |
529 | } | |
530 | else | |
531 | return MR_PERM; | |
532 | } | |
533 | ||
534 | /* If moving to a new subnet, make sure user is on acl there */ | |
535 | id = *(int *)argv[9 + idx]; | |
536 | if (id != snid) | |
537 | { | |
538 | EXEC SQL SELECT owner_type, owner_id INTO :stype, :sid | |
539 | FROM subnet WHERE snet_id=:id; | |
540 | if (!find_member(stype, sid, cl)) | |
541 | return MR_PERM; | |
542 | } | |
543 | ||
544 | return MR_SUCCESS; | |
545 | } | |
546 | } | |
547 | ||
548 | ||
549 | /* access_ahal - check for adding a host alias. | |
550 | * successful if host has less then 2 aliases and (client is owner of | |
551 | * host or subnet). | |
552 | * If deleting an alias, any owner will do. | |
553 | */ | |
554 | ||
555 | int access_ahal(struct query *q, char *argv[], client *cl) | |
556 | { | |
557 | EXEC SQL BEGIN DECLARE SECTION; | |
558 | int cnt, id, mid, sid; | |
559 | char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE]; | |
560 | EXEC SQL END DECLARE SECTION; | |
561 | int status; | |
562 | ||
563 | if (q->type == RETRIEVE) | |
564 | return MR_SUCCESS; | |
565 | ||
566 | id = *(int *)argv[1]; | |
567 | ||
568 | if (q->type == APPEND && isdigit(argv[0][0])) | |
569 | return MR_BAD_CHAR; | |
570 | ||
571 | EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id; | |
572 | if (dbms_errno) | |
573 | return mr_errcode; | |
574 | /* if the type is APPEND, this is ahal and we need to make sure there | |
575 | * will be no more than 2 aliases. If it's not, it must be dhal and | |
576 | * any owner will do. | |
577 | */ | |
578 | if (q->type == APPEND && cnt >= 2) | |
579 | return MR_PERM; | |
580 | EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id | |
581 | INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s | |
582 | WHERE m.mach_id = :id and s.snet_id = m.snet_id; | |
583 | status = find_member(mtype, mid, cl); | |
584 | if (status) | |
585 | return MR_SUCCESS; | |
586 | status = find_member(stype, sid, cl); | |
587 | if (status) | |
588 | return MR_SUCCESS; | |
589 | else | |
590 | return MR_PERM; | |
591 | } | |
592 | ||
593 | ||
594 | /* access_snt - check for retrieving network structure | |
595 | */ | |
596 | ||
597 | int access_snt(struct query *q, char *argv[], client *cl) | |
598 | { | |
599 | if (q->type == RETRIEVE) | |
600 | return MR_SUCCESS; | |
601 | ||
602 | return MR_PERM; | |
603 | } | |
604 | ||
605 | ||
606 | /* access_printer */ | |
607 | int access_printer(struct query *q, char *argv[], client *cl) | |
608 | { | |
609 | EXEC SQL BEGIN DECLARE SECTION; | |
610 | char type[PRINTSERVERS_OWNER_TYPE_SIZE]; | |
611 | int id, mach_id; | |
612 | EXEC SQL END DECLARE SECTION; | |
613 | int status; | |
614 | ||
615 | mach_id = *(int *)argv[PRN_RM]; | |
616 | EXEC SQL SELECT owner_type, owner_id INTO :type, :id | |
617 | FROM printservers WHERE mach_id = :mach_id; | |
618 | if (sqlca.sqlcode) | |
619 | return MR_PERM; | |
620 | ||
621 | status = find_member(type, id, cl); | |
622 | if (status) | |
623 | return MR_SUCCESS; | |
624 | else | |
625 | return MR_PERM; | |
626 | } | |
627 | ||
628 | /* access_zephyr */ | |
629 | int access_zephyr(struct query *q, char *argv[], client *cl) | |
630 | { | |
631 | EXEC SQL BEGIN DECLARE SECTION; | |
632 | char type[ZEPHYR_OWNER_TYPE_SIZE]; | |
633 | char *class; | |
634 | int id; | |
635 | EXEC SQL END DECLARE SECTION; | |
636 | int status; | |
637 | ||
638 | class = argv[ZA_CLASS]; | |
639 | EXEC SQL SELECT owner_type, owner_id INTO :type, :id | |
640 | FROM zephyr WHERE class = :class; | |
641 | if (sqlca.sqlcode) | |
642 | return MR_PERM; | |
643 | ||
644 | status = find_member(type, id, cl); | |
645 | if (status) | |
646 | return MR_SUCCESS; | |
647 | else | |
648 | return MR_PERM; | |
649 | } | |
650 | ||
651 | /* access_container - check access for most container operations | |
652 | * | |
653 | * Inputs: argv[0] - cnt_id | |
654 | * q - query name | |
655 | * cl - client name | |
656 | * | |
657 | * - check if that client is a member of the access control list | |
658 | * - OR, if the query is add_machine_to_container or delete_machine_from_container | |
659 | * check if the client is a memeber of the mem_acl list | |
660 | * - if the query is update_container and the container is to be renamed and | |
661 | * it is a top-level container, only priviledged users can do it | |
662 | */ | |
663 | ||
664 | int access_container(struct query *q, char *argv[], client *cl) | |
665 | { | |
666 | EXEC SQL BEGIN DECLARE SECTION; | |
667 | int cnt_id, acl_id, memacl_id; | |
668 | char acl_type[CONTAINERS_ACL_TYPE_SIZE], memacl_type[CONTAINERS_ACL_TYPE_SIZE]; | |
669 | char name[CONTAINERS_NAME_SIZE], *newname; | |
670 | EXEC SQL END DECLARE SECTION; | |
671 | int status; | |
672 | ||
673 | cnt_id = *(int *)argv[0]; | |
674 | ||
675 | /* if amcn or dmcn, container id is the second argument */ | |
676 | if (strcmp(q->shortname, "amcn") == 0 || strcmp(q->shortname, "dmcn") == 0) | |
677 | cnt_id = *(int *)argv[1]; | |
678 | ||
679 | EXEC SQL SELECT acl_id, acl_type, memacl_id, memacl_type, name | |
680 | INTO :acl_id, :acl_type, :memacl_id, :memacl_type, :name | |
681 | FROM containers | |
682 | WHERE cnt_id = :cnt_id; | |
683 | ||
684 | if (sqlca.sqlerrd[2] != 1) | |
685 | return MR_INTERNAL; | |
686 | ||
687 | /* trim off the trailing spaces */ | |
688 | strcpy(name, strtrim(name)); | |
689 | ||
690 | /* if the query is update_container and the containers is to be renamed | |
691 | * and it is a top-level container, only dbadmin can do it */ | |
692 | if (!strcmp(q->shortname, "ucon")) | |
693 | { | |
694 | newname = argv[1]; | |
695 | if (strcmp(name, newname) && strchr(name, '/') == NULL) | |
696 | return MR_PERM; | |
697 | } | |
698 | ||
699 | /* check for client in access control list and return success right | |
700 | * away if it's there. */ | |
701 | if (find_member(acl_type, acl_id, cl)) | |
702 | return MR_SUCCESS; | |
703 | ||
704 | /* If not amcn, dmcn, we lose. */ | |
705 | if (strcmp(q->shortname, "amcn") && strcmp(q->shortname, "dmcn")) | |
706 | return MR_PERM; | |
707 | ||
708 | if (find_member(memacl_type, memacl_id, cl)) | |
709 | return MR_SUCCESS; | |
710 | ||
711 | /* Otherwise fail. */ | |
712 | return MR_PERM; | |
713 | } |