3 * Check access to queries
5 * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6 * For copying and distribution information, please see the file
10 #include <mit-copyright.h>
11 #include "mr_server.h"
18 EXEC SQL INCLUDE sqlca;
23 extern int dbms_errno, mr_errcode;
25 EXEC SQL BEGIN DECLARE SECTION;
26 extern char stmt_buf[];
27 EXEC SQL END DECLARE SECTION;
29 EXEC SQL WHENEVER SQLERROR DO dbmserr();
32 /* Specialized Access Routines */
34 /* access_user - verify that client name equals specified login name
36 * - since field validation routines are called first, a users_id is
37 * now in argv[0] instead of the login name.
40 int access_user(struct query *q, char *argv[], client *cl)
42 if (cl->users_id != *(int *)argv[0])
50 /* access_login - verify that client name equals specified login name
52 * argv[0...n] contain search info. q->
55 int access_login(struct query *q, char *argv[], client *cl)
57 EXEC SQL BEGIN DECLARE SECTION;
59 EXEC SQL END DECLARE SECTION;
64 if (!strcmp(q->shortname, "gual"))
66 EXEC SQL SELECT users_id INTO :id FROM users
67 WHERE login LIKE :argv[0] AND users_id != 0;
69 else if (!strcmp(q->shortname, "gubl"))
71 EXEC SQL SELECT users_id INTO :id FROM users u
72 WHERE u.login LIKE :argv[0] AND u.users_id != 0;
74 else if (!strcmp(q->shortname, "guau"))
76 EXEC SQL SELECT users_id INTO :id FROM users
77 WHERE unix_uid = :argv[0] AND users_id != 0;
79 else if (!strcmp(q->shortname, "gubu"))
81 EXEC SQL SELECT users_id INTO :id FROM users u
82 WHERE u.unix_uid = :argv[0] AND u.users_id != 0;
85 if (sqlca.sqlcode == SQL_NO_MATCH)
86 return MR_NO_MATCH; /* ought to be MR_USER, but this is what
87 gual returns, so we have to be consistent */
88 else if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
96 /* access_list - check access for most list operations
98 * Inputs: argv[0] - list_id
100 * argv[2] - member ID (only for queries "amtl" and "dmfl")
101 * argv[7] - group IID (only for query "ulis")
104 * - check that client is a member of the access control list
105 * - OR, if the query is add_member_to_list or delete_member_from_list
106 * and the list is public, allow access if client = member
109 int access_list(struct query *q, char *argv[], client *cl)
111 EXEC SQL BEGIN DECLARE SECTION;
112 int list_id, acl_id, flags, gid, users_id;
113 char acl_type[9], *newname;
114 EXEC SQL END DECLARE SECTION;
117 list_id = *(int *)argv[0];
118 EXEC SQL SELECT acl_id, acl_type, gid, publicflg
119 INTO :acl_id, :acl_type, :gid, :flags
121 WHERE list_id = :list_id;
123 if (sqlca.sqlerrd[2] != 1)
126 /* if amtl or dmfl and list is public allow client to add or delete self */
127 if (((!strcmp("amtl", q->shortname) && flags) ||
128 (!strcmp("dmfl", q->shortname))))
130 if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id)
132 if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id)
134 } /* if update_list, don't allow them to change the GID or rename to
135 a username other than their own */
136 else if (!strcmp("ulis", q->shortname))
138 if (!strcmp(argv[7], UNIQUE_GID))
145 if (gid != atoi(argv[7]))
149 EXEC SQL SELECT users_id INTO :users_id FROM users
150 WHERE login = :newname;
151 if ((sqlca.sqlcode != SQL_NO_MATCH) && (users_id != cl->users_id))
155 /* check for client in access control list */
156 status = find_member(acl_type, acl_id, cl);
164 /* access_visible_list - allow access to list only if it is not hidden,
165 * or if the client is on the ACL
167 * Inputs: argv[0] - list_id
168 * cl - client identifier
171 int access_visible_list(struct query *q, char *argv[], client *cl)
173 EXEC SQL BEGIN DECLARE SECTION;
174 int list_id, acl_id, flags ;
176 EXEC SQL END DECLARE SECTION;
179 list_id = *(int *)argv[0];
180 EXEC SQL SELECT hidden, acl_id, acl_type
181 INTO :flags, :acl_id, :acl_type
183 WHERE list_id = :list_id;
184 if (sqlca.sqlerrd[2] != 1)
189 /* check for client in access control list */
190 status = find_member(acl_type, acl_id, cl);
198 /* access_vis_list_by_name - allow access to list only if it is not hidden,
199 * or if the client is on the ACL
201 * Inputs: argv[0] - list name
202 * cl - client identifier
205 int access_vis_list_by_name(struct query *q, char *argv[], client *cl)
207 EXEC SQL BEGIN DECLARE SECTION;
208 int acl_id, flags, rowcount;
209 char acl_type[9], *listname;
210 EXEC SQL END DECLARE SECTION;
214 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
215 FROM list WHERE name = :listname;
217 rowcount = sqlca.sqlerrd[2];
225 /* check for client in access control list */
226 status = find_member(acl_type, acl_id, cl);
234 /* access_member - allow user to access member of type "USER" and name matches
235 * username, or to access member of type "KERBEROS" and the principal matches
236 * the user, or to access member of type "LIST" and list is one that user is
237 * on the acl of, or the list is visible.
240 int access_member(struct query *q, char *argv[], client *cl)
242 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
243 return access_visible_list(q, &argv[1], cl);
245 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER"))
247 if (cl->users_id == *(int *)argv[1])
251 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS"))
253 if (cl->client_id == -*(int *)argv[1])
261 /* access_qgli - special access routine for Qualified_get_lists. Allows
262 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
265 int access_qgli(struct query *q, char *argv[], client *cl)
267 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
273 /* access_service - allow access if user is on ACL of service. Don't
274 * allow access if a wildcard is used.
277 int access_service(struct query *q, char *argv[], client *cl)
279 EXEC SQL BEGIN DECLARE SECTION;
281 char *name, acl_type[9];
282 EXEC SQL END DECLARE SECTION;
287 for (c = name; *c; c++)
292 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
294 if (sqlca.sqlerrd[2] > 1)
297 /* check for client in access control list */
298 status = find_member(acl_type, acl_id, cl);
306 /* access_filesys - verify that client is owner or on owners list of filesystem
310 int access_filesys(struct query *q, char *argv[], client *cl)
312 EXEC SQL BEGIN DECLARE SECTION;
313 int users_id, list_id;
315 EXEC SQL END DECLARE SECTION;
319 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
322 if (sqlca.sqlerrd[2] != 1)
324 if (users_id == cl->users_id)
326 status = find_member("LIST", list_id, cl);
334 /* access_host - successful if owner of host, or subnet containing host
337 int host_access_level = 0; /* 1 for network, 2 for host */
339 int access_host(struct query *q, char *argv[], client *cl)
341 EXEC SQL BEGIN DECLARE SECTION;
343 char mtype[9], stype[9];
344 EXEC SQL END DECLARE SECTION;
347 if (q->type == APPEND)
349 id = *(int *)argv[8];
350 EXEC SQL SELECT s.owner_type, s.owner_id
351 INTO :stype, :sid FROM subnet s
352 WHERE s.snet_id = :id;
355 else if (q->type == RETRIEVE)
357 if (strcmp(argv[0], "*") || strcmp(argv[1], "*") ||
358 strcmp(argv[2], "*") || strcmp(argv[3], "*"))
365 id = *(int *)argv[0];
366 EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
367 INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
368 WHERE m.mach_id = :id and s.snet_id = m.snet_id;
370 if (sqlca.sqlerrd[2] != 1)
373 status = find_member(stype, sid, cl);
376 host_access_level = 1;
379 status = find_member(mtype, mid, cl);
382 host_access_level = 2;
390 /* access_ahal - check for adding a host alias.
391 * successful if host has less then 2 aliases and (client is owner of
393 * If deleting an alias, any owner will do.
396 int access_ahal(struct query *q, char *argv[], client *cl)
398 EXEC SQL BEGIN DECLARE SECTION;
399 int cnt, id, mid, sid;
400 char mtype[256], stype[256];
401 EXEC SQL END DECLARE SECTION;
404 if (q->type == RETRIEVE)
407 id = *(int *)argv[1];
409 EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
412 /* if the type is APPEND, this is ahal and we need to make sure there
413 * will be no more than 2 aliases. If it's not, it must be dhal and
416 if (q->type == APPEND && cnt >= 2)
418 EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
419 INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
420 WHERE m.mach_id = :id and s.snet_id = m.snet_id;
421 status = find_member(mtype, mid, cl);
424 status = find_member(stype, sid, cl);
433 /* access_snt - check for retrieving network structure
436 int access_snt(struct query *q, char *argv[], client *cl)
438 if (q->type == RETRIEVE)