]> andersk Git - moira.git/blob - server/qaccess.pc
Only output groups which have the nfsgroup bit set into generated
[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
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;
131   char acl_type[LIST_ACL_TYPE_SIZE], name[LIST_NAME_SIZE], *newname;
132   EXEC SQL END DECLARE SECTION;
133   int status;
134
135   list_id = *(int *)argv[0];
136   EXEC SQL SELECT acl_id, acl_type, gid, publicflg, name
137     INTO :acl_id, :acl_type, :gid, :flags, :name
138     FROM list
139     WHERE list_id = :list_id;
140
141   if (sqlca.sqlerrd[2] != 1)
142     return MR_INTERNAL;
143
144   /* Allow client to add self to public list or delete self from any
145    * list.
146    */
147   if ((((!strcmp("amtl", q->shortname) ||
148          !strcmp("atml", q->shortname)) && flags) ||
149        (!strcmp("dmfl", q->shortname))))
150     {
151       if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id)
152         return MR_SUCCESS;
153       if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id)
154         return MR_SUCCESS;
155     } /* if update_list, don't allow them to change the GID or rename to
156          a username other than their own */
157   else if (!strcmp("ulis", q->shortname))
158     {
159       if (!strcmp(argv[7], UNIQUE_GID))
160         {
161           if (gid != -1)
162             return MR_PERM;
163         }
164       else
165         {
166           if (gid != atoi(argv[7]))
167             return MR_PERM;
168         }
169       newname = argv[1];
170       EXEC SQL SELECT users_id INTO :users_id FROM users
171         WHERE login = :newname;
172       if ((sqlca.sqlcode != SQL_NO_MATCH) && strcmp(strtrim(name), newname) &&
173           (users_id != cl->users_id))
174         return MR_PERM;
175     }
176
177   /* check for client in access control list */
178   status = find_member(acl_type, acl_id, cl);
179   if (!status)
180     return MR_PERM;
181
182   return MR_SUCCESS;
183 }
184
185
186 /* access_visible_list - allow access to list only if it is not hidden,
187  *      or if the client is on the ACL
188  *
189  * Inputs: argv[0] - list_id
190  *         cl - client identifier
191  */
192
193 int access_visible_list(struct query *q, char *argv[], client *cl)
194 {
195   EXEC SQL BEGIN DECLARE SECTION;
196   int list_id, acl_id, flags ;
197   char acl_type[LIST_ACL_TYPE_SIZE];
198   EXEC SQL END DECLARE SECTION;
199   int status;
200
201   list_id = *(int *)argv[0];
202   EXEC SQL SELECT hidden, acl_id, acl_type
203     INTO :flags, :acl_id, :acl_type
204     FROM list
205     WHERE list_id = :list_id;
206   if (sqlca.sqlerrd[2] != 1)
207     return MR_INTERNAL;
208   if (!flags)
209     return MR_SUCCESS;
210
211   /* check for client in access control list */
212   status = find_member(acl_type, acl_id, cl);
213   if (!status)
214     return MR_PERM;
215
216   return MR_SUCCESS;
217 }
218
219
220 /* access_vis_list_by_name - allow access to list only if it is not hidden,
221  *      or if the client is on the ACL
222  *
223  * Inputs: argv[0] - list name
224  *         cl - client identifier
225  */
226
227 int access_vis_list_by_name(struct query *q, char *argv[], client *cl)
228 {
229   EXEC SQL BEGIN DECLARE SECTION;
230   int acl_id, flags, rowcount;
231   char acl_type[LIST_ACL_TYPE_SIZE], *listname;
232   EXEC SQL END DECLARE SECTION;
233   int status;
234
235   listname = argv[0];
236   EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
237     FROM list WHERE name = :listname;
238
239   rowcount = sqlca.sqlerrd[2];
240   if (rowcount > 1)
241     return MR_WILDCARD;
242   if (rowcount == 0)
243     return MR_NO_MATCH;
244   if (!flags)
245     return MR_SUCCESS;
246
247   /* check for client in access control list */
248   status = find_member(acl_type, acl_id, cl);
249   if (!status)
250     return MR_PERM;
251
252   return MR_SUCCESS;
253 }
254
255
256 /* access_member - allow user to access member of type "USER" and name matches
257  * username, or to access member of type "KERBEROS" and the principal matches
258  * the user, or to access member of type "LIST" and list is one that user is
259  * on the acl of, or the list is visible.
260  */
261
262 int access_member(struct query *q, char *argv[], client *cl)
263 {
264   if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
265     return access_visible_list(q, &argv[1], cl);
266
267   if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER"))
268     {
269       if (cl->users_id == *(int *)argv[1])
270         return MR_SUCCESS;
271     }
272
273   if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS"))
274     {
275       if (cl->client_id == -*(int *)argv[1])
276         return MR_SUCCESS;
277     }
278
279   return MR_PERM;
280 }
281
282
283 /* access_qgli - special access routine for Qualified_get_lists.  Allows
284  * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
285  */
286
287 int access_qgli(struct query *q, char *argv[], client *cl)
288 {
289   if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
290     return MR_SUCCESS;
291   return MR_PERM;
292 }
293
294
295 /* access_service - allow access if user is on ACL of service.  Don't
296  * allow access if a wildcard is used.
297  */
298
299 int access_service(struct query *q, char *argv[], client *cl)
300 {
301   EXEC SQL BEGIN DECLARE SECTION;
302   int acl_id;
303   char *name, acl_type[LIST_ACL_TYPE_SIZE];
304   EXEC SQL END DECLARE SECTION;
305   int status;
306   char *c;
307
308   name = argv[0];
309   for (c = name; *c; c++)
310     {
311       if (islower(*c))
312         *c = toupper(*c);
313     }
314   EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
315     WHERE name = :name;
316   if (sqlca.sqlerrd[2] > 1)
317     return MR_PERM;
318
319   /* check for client in access control list */
320   status = find_member(acl_type, acl_id, cl);
321   if (!status)
322     return MR_PERM;
323
324   return MR_SUCCESS;
325 }
326
327
328 /* access_filesys - verify that client is owner or on owners list of filesystem
329  *      named by argv[0]
330  */
331
332 int access_filesys(struct query *q, char *argv[], client *cl)
333 {
334   EXEC SQL BEGIN DECLARE SECTION;
335   int users_id, list_id;
336   char *name;
337   EXEC SQL END DECLARE SECTION;
338   int status;
339
340   name = argv[0];
341   EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
342     WHERE label = :name;
343
344   if (sqlca.sqlerrd[2] != 1)
345     return MR_PERM;
346   if (users_id == cl->users_id)
347     return MR_SUCCESS;
348   status = find_member("LIST", list_id, cl);
349   if (status)
350     return MR_SUCCESS;
351   else
352     return MR_PERM;
353 }
354
355
356 /* access_host - successful if owner of host, or subnet containing host
357  */
358
359 int access_host(struct query *q, char *argv[], client *cl)
360 {
361   EXEC SQL BEGIN DECLARE SECTION;
362   int mid, sid, id;
363   char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
364   EXEC SQL END DECLARE SECTION;
365   int status;
366
367   if (q->type == RETRIEVE)
368     {
369       if (strcmp(argv[0], "*") || strcmp(argv[1], "*") ||
370           strcmp(argv[2], "*") || strcmp(argv[3], "*"))
371         return MR_SUCCESS;
372       else
373         return MR_PERM;
374     }
375
376   if (q->type == APPEND)
377     {
378       /* Non-query owner must set use to zero */
379       if (atoi(argv[6]) != 0)
380         return MR_PERM;
381
382       /* ... and start the hostname with a letter */
383       if (isdigit(argv[0][0]))
384         return MR_BAD_CHAR;
385
386       id = *(int *)argv[8];
387       EXEC SQL SELECT s.owner_type, s.owner_id
388         INTO :stype, :sid FROM subnet s
389         WHERE s.snet_id = :id;
390       mid = 0;
391
392       if (find_member(stype, sid, cl))
393         return MR_SUCCESS;
394       else
395         return MR_PERM;
396     }
397   else /* q-type == UPDATE */
398     {
399       EXEC SQL BEGIN DECLARE SECTION;
400       int status, acomment, use, ocomment, snid;
401       char contact[MACHINE_CONTACT_SIZE], address[MACHINE_ADDRESS_SIZE];
402       char name[MACHINE_NAME_SIZE];
403       EXEC SQL END DECLARE SECTION;
404
405       id = *(int *)argv[0];
406       EXEC SQL SELECT m.name, m.use, m.contact, m.status, m.address,
407         m.owner_type, m.owner_id, m.acomment, m.ocomment, m.snet_id,
408         s.owner_type, s.owner_id INTO :name, :use, :contact, :status,
409         :address, :mtype, :mid, :acomment, :ocomment, :snid, :stype, :sid
410         FROM machine m, subnet s
411         WHERE m.mach_id = :id AND s.snet_id = m.snet_id;
412       if (dbms_errno)
413         return mr_errcode;
414
415       /* non-query-owner cannot change use or ocomment */
416       if ((use != atoi(argv[7])) || (ocomment != *(int *)argv[14]))
417         return MR_PERM;
418
419       /* or rename to start with digit */
420       if (isdigit(argv[1][0]) && strcmp(strtrim(name), argv[1]))
421         return MR_BAD_CHAR;
422
423       if (!find_member(stype, sid, cl))
424         {
425           if (find_member(mtype, mid, cl))
426             {
427               /* host owner also cannot change contact, status, address,
428                  owner, or acomment */
429               if (strcmp(argv[6], strtrim(contact)) ||
430                   (status != atoi(argv[8])) ||
431                   strcmp(argv[10], strtrim(address)) ||
432                   strcmp(argv[11], strtrim(mtype)) ||
433                   (mid != *(int *)argv[12]) || (acomment != *(int *)argv[13]))
434                 return MR_PERM;
435             }
436           else
437             return MR_PERM;
438         }
439
440       /* If moving to a new subnet, make sure user is on acl there */
441       id = *(int *)argv[9];
442       if (id != snid)
443         {
444           EXEC SQL SELECT owner_type, owner_id INTO :stype, :sid
445             FROM subnet WHERE snet_id=:id;
446           if (!find_member(stype, sid, cl))
447             return MR_PERM;
448         }
449
450       return MR_SUCCESS;
451     }
452 }
453
454
455 /* access_ahal - check for adding a host alias.
456  * successful if host has less then 2 aliases and (client is owner of
457  * host or subnet).
458  * If deleting an alias, any owner will do.
459  */
460
461 int access_ahal(struct query *q, char *argv[], client *cl)
462 {
463   EXEC SQL BEGIN DECLARE SECTION;
464   int cnt, id, mid, sid;
465   char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
466   EXEC SQL END DECLARE SECTION;
467   int status;
468
469   if (q->type == RETRIEVE)
470     return MR_SUCCESS;
471
472   id = *(int *)argv[1];
473
474   if (q->type == APPEND && isdigit(argv[0][0]))
475     return MR_BAD_CHAR;
476
477   EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
478   if (dbms_errno)
479     return mr_errcode;
480   /* if the type is APPEND, this is ahal and we need to make sure there
481    * will be no more than 2 aliases.  If it's not, it must be dhal and
482    * any owner will do.
483    */
484   if (q->type == APPEND && cnt >= 2)
485     return MR_PERM;
486   EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
487     INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
488     WHERE m.mach_id = :id and s.snet_id = m.snet_id;
489   status = find_member(mtype, mid, cl);
490   if (status)
491     return MR_SUCCESS;
492   status = find_member(stype, sid, cl);
493   if (status)
494     return MR_SUCCESS;
495   else
496     return MR_PERM;
497 }
498
499
500 /* access_snt - check for retrieving network structure
501  */
502
503 int access_snt(struct query *q, char *argv[], client *cl)
504 {
505   if (q->type == RETRIEVE)
506     return MR_SUCCESS;
507
508   return MR_PERM;
509 }
510
511
512 /* access_printer */
513 int access_printer(struct query *q, char *argv[], client *cl)
514 {
515   EXEC SQL BEGIN DECLARE SECTION;
516   char type[PRINTSERVERS_OWNER_TYPE_SIZE];
517   int id, mach_id;
518   EXEC SQL END DECLARE SECTION;
519   int status;
520
521   mach_id = *(int *)argv[PRN_RM];
522   EXEC SQL SELECT owner_type, owner_id INTO :type, :id
523     FROM printservers WHERE mach_id = :mach_id;
524   if (sqlca.sqlcode)
525     return MR_PERM;
526
527   status = find_member(type, id, cl);
528   if (status)
529     return MR_SUCCESS;
530   else
531     return MR_PERM;
532 }
This page took 0.099295 seconds and 5 git commands to generate.