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