6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
13 static char *rcsid_qsupport_dc = "$Header$";
16 #include <mit-copyright.h>
17 #include "mr_server.h"
20 EXEC SQL INCLUDE sqlca;
24 extern int dbms_errno, mr_errcode;
26 EXEC SQL BEGIN DECLARE SECTION;
27 extern char stmt_buf[];
28 EXEC SQL END DECLARE SECTION;
30 EXEC SQL WHENEVER SQLERROR DO dbmserr();
33 /* Specialized Access Routines */
35 /* access_user - verify that client name equals specified login name
37 * - since field validation routines are called first, a users_id is
38 * now in argv[0] instead of the login name.
41 int access_user(struct query *q, char *argv[], client *cl)
43 if (cl->users_id != *(int *)argv[0])
51 /* access_login - verify that client name equals specified login name
53 * argv[0...n] contain search info. q->
56 int access_login(struct query *q, char *argv[], client *cl)
58 EXEC SQL BEGIN DECLARE SECTION;
60 EXEC SQL END DECLARE SECTION;
65 if (!strcmp(q->shortname, "gual"))
67 EXEC SQL SELECT users_id INTO :id FROM users
68 WHERE login LIKE :argv[0] AND users_id != 0;
70 else if (!strcmp(q->shortname, "gubl"))
72 EXEC SQL SELECT users_id INTO :id FROM users u
73 WHERE u.login LIKE :argv[0] AND u.users_id != 0;
75 else if (!strcmp(q->shortname, "guau"))
77 EXEC SQL SELECT users_id INTO :id FROM users
78 WHERE unix_uid = :argv[0] AND users_id != 0;
80 else if (!strcmp(q->shortname, "gubu"))
82 EXEC SQL SELECT users_id INTO :id FROM users u
83 WHERE u.unix_uid = :argv[0] AND u.users_id != 0;
86 if (sqlca.sqlcode == SQL_NO_MATCH)
87 return MR_NO_MATCH; /* ought to be MR_USER, but this is what
88 gual returns, so we have to be consistent */
89 else if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
97 /* access_list - check access for most list operations
99 * Inputs: argv[0] - list_id
101 * argv[2] - member ID (only for queries "amtl" and "dmfl")
102 * argv[7] - group IID (only for query "ulis")
105 * - check that client is a member of the access control list
106 * - OR, if the query is add_member_to_list or delete_member_from_list
107 * and the list is public, allow access if client = member
110 int access_list(struct query *q, char *argv[], client *cl)
112 EXEC SQL BEGIN DECLARE SECTION;
113 int list_id, acl_id, flags, gid, users_id;
114 char acl_type[9], *newname;
115 EXEC SQL END DECLARE SECTION;
118 list_id = *(int *)argv[0];
119 EXEC SQL SELECT acl_id, acl_type, gid, publicflg
120 INTO :acl_id, :acl_type, :gid, :flags
122 WHERE list_id = :list_id;
124 if (sqlca.sqlerrd[2] != 1)
127 /* if amtl or dmfl and list is public allow client to add or delete self */
128 if (((!strcmp("amtl", q->shortname) && flags) ||
129 (!strcmp("dmfl", q->shortname))))
131 if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id)
133 if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id)
135 } /* if update_list, don't allow them to change the GID or rename to
136 a username other than their own */
137 else if (!strcmp("ulis", q->shortname))
139 if (!strcmp(argv[7], UNIQUE_GID))
146 if (gid != atoi(argv[7]))
150 EXEC SQL SELECT users_id INTO :users_id FROM users
151 WHERE login = :newname;
152 if ((sqlca.sqlcode != SQL_NO_MATCH) && (users_id != cl->users_id))
156 /* check for client in access control list */
157 status = find_member(acl_type, acl_id, cl);
165 /* access_visible_list - allow access to list only if it is not hidden,
166 * or if the client is on the ACL
168 * Inputs: argv[0] - list_id
169 * cl - client identifier
172 int access_visible_list(struct query *q, char *argv[], client *cl)
174 EXEC SQL BEGIN DECLARE SECTION;
175 int list_id, acl_id, flags ;
177 EXEC SQL END DECLARE SECTION;
180 list_id = *(int *)argv[0];
181 EXEC SQL SELECT hidden, acl_id, acl_type
182 INTO :flags, :acl_id, :acl_type
184 WHERE list_id = :list_id;
185 if (sqlca.sqlerrd[2] != 1)
190 /* check for client in access control list */
191 status = find_member(acl_type, acl_id, cl);
199 /* access_vis_list_by_name - allow access to list only if it is not hidden,
200 * or if the client is on the ACL
202 * Inputs: argv[0] - list name
203 * cl - client identifier
206 int access_vis_list_by_name(struct query *q, char *argv[], client *cl)
208 EXEC SQL BEGIN DECLARE SECTION;
209 int acl_id, flags, rowcount;
210 char acl_type[9], *listname;
211 EXEC SQL END DECLARE SECTION;
215 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
216 FROM list WHERE name = :listname;
218 rowcount = sqlca.sqlerrd[2];
226 /* check for client in access control list */
227 status = find_member(acl_type, acl_id, cl);
235 /* access_member - allow user to access member of type "USER" and name matches
236 * username, or to access member of type "KERBEROS" and the principal matches
237 * the user, or to access member of type "LIST" and list is one that user is
238 * on the acl of, or the list is visible.
241 int access_member(struct query *q, char *argv[], client *cl)
243 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
244 return access_visible_list(q, &argv[1], cl);
246 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER"))
248 if (cl->users_id == *(int *)argv[1])
252 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS"))
254 if (cl->client_id == -*(int *)argv[1])
262 /* access_qgli - special access routine for Qualified_get_lists. Allows
263 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
266 int access_qgli(struct query *q, char *argv[], client *cl)
268 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
274 /* access_service - allow access if user is on ACL of service. Don't
275 * allow access if a wildcard is used.
278 int access_service(struct query *q, char *argv[], client *cl)
280 EXEC SQL BEGIN DECLARE SECTION;
282 char *name, acl_type[9];
283 EXEC SQL END DECLARE SECTION;
288 for (c = name; *c; c++)
293 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
295 if (sqlca.sqlerrd[2] > 1)
298 /* check for client in access control list */
299 status = find_member(acl_type, acl_id, cl);
307 /* access_filesys - verify that client is owner or on owners list of filesystem
311 int access_filesys(struct query *q, char *argv[], client *cl)
313 EXEC SQL BEGIN DECLARE SECTION;
314 int users_id, list_id;
316 EXEC SQL END DECLARE SECTION;
320 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
323 if (sqlca.sqlerrd[2] != 1)
325 if (users_id == cl->users_id)
327 status = find_member("LIST", list_id, cl);
335 /* access_host - successful if owner of host, or subnet containing host
338 int host_access_level = 0; /* 1 for network, 2 for host */
340 int access_host(struct query *q, char *argv[], client *cl)
342 EXEC SQL BEGIN DECLARE SECTION;
344 char mtype[9], stype[9];
345 EXEC SQL END DECLARE SECTION;
348 if (q->type == APPEND)
350 id = *(int *)argv[8];
351 EXEC SQL SELECT s.owner_type, s.owner_id
352 INTO :stype, :sid FROM subnet s
353 WHERE s.snet_id = :id;
356 else if (q->type == RETRIEVE)
358 if (strcmp(argv[0], "*") || strcmp(argv[1], "*") ||
359 strcmp(argv[2], "*") || strcmp(argv[3], "*"))
366 id = *(int *)argv[0];
367 EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
368 INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
369 WHERE m.mach_id = :id and s.snet_id = m.snet_id;
371 if (sqlca.sqlerrd[2] != 1)
374 status = find_member(stype, sid, cl);
377 host_access_level = 1;
380 status = find_member(mtype, mid, cl);
383 host_access_level = 2;
391 /* access_ahal - check for adding a host alias.
392 * successful if host has less then 2 aliases and (client is owner of
394 * If deleting an alias, any owner will do.
397 int access_ahal(struct query *q, char *argv[], client *cl)
399 EXEC SQL BEGIN DECLARE SECTION;
400 int cnt, id, mid, sid;
401 char mtype[256], stype[256];
402 EXEC SQL END DECLARE SECTION;
405 if (q->type == RETRIEVE)
408 id = *(int *)argv[1];
410 EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
413 /* if the type is APPEND, this is ahal and we need to make sure there
414 * will be no more than 2 aliases. If it's not, it must be dhal and
417 if (q->type == APPEND && cnt >= 2)
419 EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
420 INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
421 WHERE m.mach_id = :id and s.snet_id = m.snet_id;
422 status = find_member(mtype, mid, cl);
425 status = find_member(stype, sid, cl);
434 /* access_snt - check for retrieving network structure
437 int access_snt(struct query *q, char *argv[], client *cl)
439 if (q->type == RETRIEVE)