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