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 WHENEVER SQLERROR DO dbmserr();
28 /* Specialized Access Routines */
30 /* access_user - verify that client name equals specified login name
32 * - since field validation routines are called first, a users_id is
33 * now in argv[0] instead of the login name.
36 int access_user(struct query *q, char *argv[], client *cl)
38 if (cl->users_id != *(int *)argv[0])
46 /* access_login - verify that client name equals specified login name
48 * argv[0...n] contain search info. q->
51 int access_login(struct query *q, char *argv[], client *cl)
53 EXEC SQL BEGIN DECLARE SECTION;
55 EXEC SQL END DECLARE SECTION;
60 if (!strcmp(q->shortname, "gual"))
62 EXEC SQL SELECT users_id INTO :id FROM users
63 WHERE login = :argv[0] AND users_id != 0;
65 else if (!strcmp(q->shortname, "gubl"))
67 EXEC SQL SELECT users_id INTO :id FROM users u
68 WHERE u.login = :argv[0] AND u.users_id != 0;
70 else if (!strcmp(q->shortname, "guau"))
72 EXEC SQL SELECT users_id INTO :id FROM users
73 WHERE unix_uid = :argv[0] AND users_id != 0;
75 else if (!strcmp(q->shortname, "gubu"))
77 EXEC SQL SELECT users_id INTO :id FROM users u
78 WHERE u.unix_uid = :argv[0] AND u.users_id != 0;
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)
92 /* access_list - check access for most list operations
94 * Inputs: argv[0] - list_id
96 * argv[2] - member ID (only for queries "amtl" and "dmfl")
97 * argv[7] - group ID (only for query "ulis")
100 * - check that client is a member of the access control list
101 * - OR, if the query is add_member_to_list or delete_member_from_list
102 * and the list is public, allow access if client = member
105 int access_list(struct query *q, char *argv[], client *cl)
107 EXEC SQL BEGIN DECLARE SECTION;
108 int list_id, acl_id, flags, gid, users_id;
109 char acl_type[LIST_ACL_TYPE_SIZE], name[LIST_NAME_SIZE], *newname;
110 EXEC SQL END DECLARE SECTION;
113 list_id = *(int *)argv[0];
114 EXEC SQL SELECT acl_id, acl_type, gid, publicflg, name
115 INTO :acl_id, :acl_type, :gid, :flags, :name
117 WHERE list_id = :list_id;
119 if (sqlca.sqlerrd[2] != 1)
122 /* if amtl or dmfl and list is public allow client to add or delete self */
123 if (((!strcmp("amtl", q->shortname) && flags) ||
124 (!strcmp("dmfl", q->shortname))))
126 if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id)
128 if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id)
130 } /* if update_list, don't allow them to change the GID or rename to
131 a username other than their own */
132 else if (!strcmp("ulis", q->shortname))
134 if (!strcmp(argv[7], UNIQUE_GID))
141 if (gid != atoi(argv[7]))
145 EXEC SQL SELECT users_id INTO :users_id FROM users
146 WHERE login = :newname;
147 if ((sqlca.sqlcode != SQL_NO_MATCH) && strcmp(strtrim(name), newname) &&
148 (users_id != cl->users_id))
152 /* check for client in access control list */
153 status = find_member(acl_type, acl_id, cl);
161 /* access_visible_list - allow access to list only if it is not hidden,
162 * or if the client is on the ACL
164 * Inputs: argv[0] - list_id
165 * cl - client identifier
168 int access_visible_list(struct query *q, char *argv[], client *cl)
170 EXEC SQL BEGIN DECLARE SECTION;
171 int list_id, acl_id, flags ;
172 char acl_type[LIST_ACL_TYPE_SIZE];
173 EXEC SQL END DECLARE SECTION;
176 list_id = *(int *)argv[0];
177 EXEC SQL SELECT hidden, acl_id, acl_type
178 INTO :flags, :acl_id, :acl_type
180 WHERE list_id = :list_id;
181 if (sqlca.sqlerrd[2] != 1)
186 /* check for client in access control list */
187 status = find_member(acl_type, acl_id, cl);
195 /* access_vis_list_by_name - allow access to list only if it is not hidden,
196 * or if the client is on the ACL
198 * Inputs: argv[0] - list name
199 * cl - client identifier
202 int access_vis_list_by_name(struct query *q, char *argv[], client *cl)
204 EXEC SQL BEGIN DECLARE SECTION;
205 int acl_id, flags, rowcount;
206 char acl_type[LIST_ACL_TYPE_SIZE], *listname;
207 EXEC SQL END DECLARE SECTION;
211 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
212 FROM list WHERE name = :listname;
214 rowcount = sqlca.sqlerrd[2];
222 /* check for client in access control list */
223 status = find_member(acl_type, acl_id, cl);
231 /* access_member - allow user to access member of type "USER" and name matches
232 * username, or to access member of type "KERBEROS" and the principal matches
233 * the user, or to access member of type "LIST" and list is one that user is
234 * on the acl of, or the list is visible.
237 int access_member(struct query *q, char *argv[], client *cl)
239 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
240 return access_visible_list(q, &argv[1], cl);
242 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER"))
244 if (cl->users_id == *(int *)argv[1])
248 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS"))
250 if (cl->client_id == -*(int *)argv[1])
258 /* access_qgli - special access routine for Qualified_get_lists. Allows
259 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
262 int access_qgli(struct query *q, char *argv[], client *cl)
264 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
270 /* access_service - allow access if user is on ACL of service. Don't
271 * allow access if a wildcard is used.
274 int access_service(struct query *q, char *argv[], client *cl)
276 EXEC SQL BEGIN DECLARE SECTION;
278 char *name, acl_type[LIST_ACL_TYPE_SIZE];
279 EXEC SQL END DECLARE SECTION;
284 for (c = name; *c; c++)
289 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
291 if (sqlca.sqlerrd[2] > 1)
294 /* check for client in access control list */
295 status = find_member(acl_type, acl_id, cl);
303 /* access_filesys - verify that client is owner or on owners list of filesystem
307 int access_filesys(struct query *q, char *argv[], client *cl)
309 EXEC SQL BEGIN DECLARE SECTION;
310 int users_id, list_id;
312 EXEC SQL END DECLARE SECTION;
316 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
319 if (sqlca.sqlerrd[2] != 1)
321 if (users_id == cl->users_id)
323 status = find_member("LIST", list_id, cl);
331 /* access_host - successful if owner of host, or subnet containing host
334 int access_host(struct query *q, char *argv[], client *cl)
336 EXEC SQL BEGIN DECLARE SECTION;
338 char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
339 EXEC SQL END DECLARE SECTION;
342 if (q->type == RETRIEVE)
344 if (strcmp(argv[0], "*") || strcmp(argv[1], "*") ||
345 strcmp(argv[2], "*") || strcmp(argv[3], "*"))
351 if (q->type == APPEND)
353 /* Non-query owner must set use to zero */
354 if (atoi(argv[6]) != 0)
357 id = *(int *)argv[8];
358 EXEC SQL SELECT s.owner_type, s.owner_id
359 INTO :stype, :sid FROM subnet s
360 WHERE s.snet_id = :id;
363 if (find_member(stype, sid, cl))
368 else /* q-type == UPDATE */
370 EXEC SQL BEGIN DECLARE SECTION;
371 int status, acomment, use, ocomment, snid;
372 char contact[MACHINE_CONTACT_SIZE], address[MACHINE_ADDRESS_SIZE];
373 EXEC SQL END DECLARE SECTION;
375 id = *(int *)argv[0];
376 EXEC SQL SELECT m.use, m.contact, m.status, m.address, m.owner_type,
377 m.owner_id, m.acomment, m.ocomment, m.snet_id, s.owner_type, s.owner_id
378 INTO :use, :contact, :status, :address, :mtype, :mid, :acomment,
379 :ocomment, :snid, :stype, :sid
380 FROM machine m, subnet s
381 WHERE m.mach_id = :id AND s.snet_id = m.snet_id;
385 /* non-query-owner cannot change use or ocomment */
386 if ((use != atoi(argv[7])) || (ocomment != *(int *)argv[14]))
389 if (!find_member(stype, sid, cl))
391 if (find_member(mtype, mid, cl))
393 /* host owner also cannot change contact, status, address,
394 owner, or acomment */
395 if (strcmp(argv[6], strtrim(contact)) ||
396 (status != atoi(argv[8])) ||
397 strcmp(argv[10], strtrim(address)) ||
398 strcmp(argv[11], strtrim(mtype)) ||
399 (mid != *(int *)argv[12]) || (acomment != *(int *)argv[13]))
406 /* If moving to a new subnet, make sure user is on acl there */
407 id = *(int *)argv[9];
410 EXEC SQL SELECT owner_type, owner_id INTO :stype, :sid
411 FROM subnet WHERE snet_id=:id;
412 if (!find_member(stype, sid, cl))
421 /* access_ahal - check for adding a host alias.
422 * successful if host has less then 2 aliases and (client is owner of
424 * If deleting an alias, any owner will do.
427 int access_ahal(struct query *q, char *argv[], client *cl)
429 EXEC SQL BEGIN DECLARE SECTION;
430 int cnt, id, mid, sid;
431 char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
432 EXEC SQL END DECLARE SECTION;
435 if (q->type == RETRIEVE)
438 id = *(int *)argv[1];
440 EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
443 /* if the type is APPEND, this is ahal and we need to make sure there
444 * will be no more than 2 aliases. If it's not, it must be dhal and
447 if (q->type == APPEND && cnt >= 2)
449 EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
450 INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
451 WHERE m.mach_id = :id and s.snet_id = m.snet_id;
452 status = find_member(mtype, mid, cl);
455 status = find_member(stype, sid, cl);
464 /* access_snt - check for retrieving network structure
467 int access_snt(struct query *q, char *argv[], client *cl)
469 if (q->type == RETRIEVE)