]>
Commit | Line | Data |
---|---|---|
73cf66ba | 1 | /* |
2 | * $Source$ | |
3 | * $Author$ | |
4 | * $Header$ | |
5 | * | |
6 | * Copyright (C) 1987 by the Massachusetts Institute of Technology | |
7 | * For copying and distribution information, please see the file | |
8 | * <mit-copyright.h>. | |
9 | * | |
10 | */ | |
11 | ||
12 | #ifndef lint | |
13 | static char *rcsid_qsupport_dc = "$Header$"; | |
14 | #endif lint | |
15 | ||
16 | #include <mit-copyright.h> | |
17 | #include "query.h" | |
18 | #include "mr_server.h" | |
19 | #include <ctype.h> | |
20 | EXEC SQL INCLUDE sqlca; | |
21 | EXEC SQL INCLUDE sqlda; | |
22 | #include "qrtn.h" | |
23 | ||
24 | extern char *whoami; | |
25 | extern int ingres_errno, mr_errcode; | |
26 | ||
27 | EXEC SQL BEGIN DECLARE SECTION; | |
28 | extern char stmt_buf[]; | |
29 | EXEC SQL END DECLARE SECTION; | |
30 | ||
31 | EXEC SQL WHENEVER SQLERROR CALL ingerr; | |
32 | ||
33 | ||
34 | /* Specialized Access Routines */ | |
35 | ||
36 | /* access_user - verify that client name equals specified login name | |
37 | * | |
38 | * - since field validation routines are called first, a users_id is | |
39 | * now in argv[0] instead of the login name. | |
40 | */ | |
41 | ||
42 | access_user(q, argv, cl) | |
43 | struct query *q; | |
44 | char *argv[]; | |
45 | client *cl; | |
46 | { | |
47 | if (cl->users_id != *(int *)argv[0]) | |
48 | return(MR_PERM); | |
49 | else | |
50 | return(MR_SUCCESS); | |
51 | } | |
52 | ||
53 | ||
54 | ||
55 | /* access_login - verify that client name equals specified login name | |
56 | * | |
57 | * argv[0...n] contain search info. q-> | |
58 | */ | |
59 | ||
60 | access_login(q, argv, cl) | |
61 | struct query *q; | |
62 | char *argv[]; | |
63 | client *cl; | |
64 | { | |
65 | EXEC SQL BEGIN DECLARE SECTION; | |
66 | int id; | |
67 | char qual[256]; | |
68 | EXEC SQL END DECLARE SECTION; | |
69 | ||
4872dc73 | 70 | /* BEGIN KLUDGE |
71 | Ingres will lose horribly if you try to look up a user with | |
72 | a username > 8 chars (which some old versions of the moira client | |
73 | still sometimes do). This routine is only called by gubl/gual and | |
74 | gubu/guau, so we know argv[0] must be <=8 chars in a correct | |
75 | query, so verify that first */ | |
76 | if(strlen(argv[0])>8) return MR_ARG_TOO_LONG; | |
77 | /* END KLUDGE */ | |
78 | ||
73cf66ba | 79 | build_qual(q->qual, q->argc, argv, qual); |
80 | if (!strncmp(q->name,"get_user_account",strlen("get_user_account"))) { | |
81 | EXEC SQL SELECT users_id INTO :id FROM users u, strings str WHERE :qual; | |
82 | } else { | |
83 | EXEC SQL SELECT users_id INTO :id FROM users u WHERE :qual; | |
84 | } | |
85 | ||
86 | if (sqlca.sqlerrd[2] != 1 || id != cl->users_id) | |
87 | return(MR_PERM); | |
88 | else | |
89 | return(MR_SUCCESS); | |
90 | } | |
91 | ||
92 | ||
93 | ||
94 | /* access_list - check access for most list operations | |
95 | * | |
96 | * Inputs: argv[0] - list_id | |
97 | * q - query name | |
98 | * argv[2] - member ID (only for queries "amtl" and "dmfl") | |
99 | * argv[7] - group IID (only for query "ulis") | |
100 | * cl - client name | |
101 | * | |
102 | * - check that client is a member of the access control list | |
103 | * - OR, if the query is add_member_to_list or delete_member_from_list | |
104 | * and the list is public, allow access if client = member | |
105 | */ | |
106 | ||
107 | access_list(q, argv, cl) | |
108 | struct query *q; | |
109 | char *argv[]; | |
110 | client *cl; | |
111 | { | |
112 | EXEC SQL BEGIN DECLARE SECTION; | |
113 | int list_id, acl_id, flags, gid; | |
114 | char acl_type[9]; | |
115 | EXEC SQL END DECLARE SECTION; | |
116 | char *client_type; | |
117 | int client_id, status; | |
118 | ||
119 | list_id = *(int *)argv[0]; | |
120 | EXEC SQL SELECT acl_id, acl_type, gid, publicflg | |
121 | INTO :acl_id, :acl_type, :gid, :flags | |
122 | FROM list | |
123 | WHERE list_id = :list_id; | |
124 | ||
125 | if (sqlca.sqlerrd[2] != 1) | |
126 | return(MR_INTERNAL); | |
127 | ||
128 | /* parse client structure */ | |
129 | if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) | |
130 | return(status); | |
131 | ||
132 | /* if amtl or dmfl and list is public allow client to add or delete self */ | |
133 | if (((!strcmp("amtl", q->shortname) && flags) || | |
134 | (!strcmp("dmfl", q->shortname))) && | |
135 | (!strcmp("USER", argv[1]))) { | |
136 | if (*(int *)argv[2] == client_id) return(MR_SUCCESS); | |
137 | /* if update_list, don't allow them to change the GID */ | |
138 | } else if (!strcmp("ulis", q->shortname)) { | |
139 | if ((!strcmp(argv[7], UNIQUE_GID) && (gid != -1)) || | |
140 | (strcmp(argv[7], UNIQUE_GID) && (gid != atoi(argv[7])))) | |
141 | return(MR_PERM); | |
142 | } | |
143 | ||
144 | /* check for client in access control list */ | |
145 | status = find_member(acl_type, acl_id, client_type, client_id, 0); | |
146 | if (!status) return(MR_PERM); | |
147 | ||
148 | return(MR_SUCCESS); | |
149 | } | |
150 | ||
151 | ||
152 | /* access_visible_list - allow access to list only if it is not hidden, | |
153 | * or if the client is on the ACL | |
154 | * | |
155 | * Inputs: argv[0] - list_id | |
156 | * cl - client identifier | |
157 | */ | |
158 | ||
159 | access_visible_list(q, argv, cl) | |
160 | struct query *q; | |
161 | char *argv[]; | |
162 | client *cl; | |
163 | { | |
164 | EXEC SQL BEGIN DECLARE SECTION; | |
165 | int list_id, acl_id, flags ; | |
166 | char acl_type[9]; | |
167 | EXEC SQL END DECLARE SECTION; | |
168 | char *client_type; | |
169 | int client_id, status; | |
170 | ||
171 | list_id = *(int *)argv[0]; | |
172 | EXEC SQL SELECT hidden, acl_id, acl_type | |
173 | INTO :flags, :acl_id, :acl_type | |
174 | FROM list | |
175 | WHERE list_id = :list_id; | |
176 | if (sqlca.sqlerrd[2] != 1) | |
177 | return(MR_INTERNAL); | |
178 | if (!flags) | |
179 | return(MR_SUCCESS); | |
180 | ||
181 | /* parse client structure */ | |
182 | if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) | |
183 | return(status); | |
184 | ||
185 | /* check for client in access control list */ | |
186 | status = find_member(acl_type, acl_id, client_type, client_id, 0); | |
187 | if (!status) | |
188 | return(MR_PERM); | |
189 | ||
190 | return(MR_SUCCESS); | |
191 | } | |
192 | ||
193 | ||
194 | /* access_vis_list_by_name - allow access to list only if it is not hidden, | |
195 | * or if the client is on the ACL | |
196 | * | |
197 | * Inputs: argv[0] - list name | |
198 | * cl - client identifier | |
199 | */ | |
200 | ||
201 | access_vis_list_by_name(q, argv, cl) | |
202 | struct query *q; | |
203 | char *argv[]; | |
204 | client *cl; | |
205 | { | |
206 | EXEC SQL BEGIN DECLARE SECTION; | |
207 | int acl_id, flags, rowcount; | |
208 | char acl_type[9], *listname; | |
209 | EXEC SQL END DECLARE SECTION; | |
210 | char *client_type; | |
211 | int client_id, status; | |
212 | ||
213 | listname = argv[0]; | |
214 | EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type | |
215 | FROM list WHERE name = :listname; | |
216 | ||
217 | rowcount=sqlca.sqlerrd[2]; | |
218 | if (rowcount > 1) | |
219 | return(MR_WILDCARD); | |
220 | if (rowcount == 0) | |
221 | return(MR_NO_MATCH); | |
222 | if (!flags) | |
223 | return(MR_SUCCESS); | |
224 | ||
225 | /* parse client structure */ | |
226 | if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) | |
227 | return(status); | |
228 | ||
229 | /* check for client in access control list */ | |
230 | status = find_member(acl_type, acl_id, client_type, client_id, 0); | |
231 | if (!status) | |
232 | return(MR_PERM); | |
233 | ||
234 | return(MR_SUCCESS); | |
235 | } | |
236 | ||
237 | ||
238 | /* access_member - allow user to access member of type "USER" and name matches | |
239 | * username, or to access member of type "LIST" and list is one that user is | |
240 | * on the acl of, or the list is visible. | |
241 | */ | |
242 | ||
243 | access_member(q, argv, cl) | |
244 | struct query *q; | |
245 | char *argv[]; | |
246 | client *cl; | |
247 | { | |
248 | if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST")) | |
249 | return(access_visible_list(q, &argv[1], cl)); | |
250 | ||
251 | if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) { | |
252 | if (cl->users_id == *(int *)argv[1]) | |
253 | return(MR_SUCCESS); | |
254 | } | |
255 | ||
256 | if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBERO")) { | |
257 | if (cl->client_id == *(int *)argv[1]) | |
258 | return(MR_SUCCESS); | |
259 | } | |
260 | ||
261 | return(MR_PERM); | |
262 | } | |
263 | ||
264 | ||
265 | /* access_qgli - special access routine for Qualified_get_lists. Allows | |
266 | * access iff argv[0] == "TRUE" and argv[2] == "FALSE". | |
267 | */ | |
268 | ||
269 | access_qgli(q, argv, cl) | |
270 | struct query *q; | |
271 | char *argv[]; | |
272 | client *cl; | |
273 | { | |
274 | if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE")) | |
275 | return(MR_SUCCESS); | |
276 | return(MR_PERM); | |
277 | } | |
278 | ||
279 | ||
280 | /* access_service - allow access if user is on ACL of service. Don't | |
281 | * allow access if a wildcard is used. | |
282 | */ | |
283 | ||
284 | access_service(q, argv, cl) | |
285 | struct query *q; | |
286 | char *argv[]; | |
287 | client *cl; | |
288 | { | |
289 | EXEC SQL BEGIN DECLARE SECTION; | |
290 | int acl_id; | |
291 | char *name, acl_type[9]; | |
292 | EXEC SQL END DECLARE SECTION; | |
293 | int client_id, status; | |
294 | char *client_type, *c; | |
295 | ||
296 | name = argv[0]; | |
297 | for(c=name;*c;c++) if(islower(*c)) *c = toupper(*c); /* uppercasify */ | |
298 | EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers | |
299 | WHERE name = :name; | |
300 | if (sqlca.sqlerrd[2] > 1) | |
301 | return(MR_PERM); | |
302 | ||
303 | /* parse client structure */ | |
304 | if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) | |
305 | return(status); | |
306 | ||
307 | /* check for client in access control list */ | |
308 | status = find_member(acl_type, acl_id, client_type, client_id, 0); | |
309 | if (!status) return(MR_PERM); | |
310 | ||
311 | return(MR_SUCCESS); | |
312 | } | |
313 | ||
314 | ||
315 | /* access_filesys - verify that client is owner or on owners list of filesystem | |
316 | * named by argv[0] | |
317 | */ | |
318 | ||
319 | access_filesys(q, argv, cl) | |
320 | struct query *q; | |
321 | char *argv[]; | |
322 | client *cl; | |
323 | { | |
324 | EXEC SQL BEGIN DECLARE SECTION; | |
325 | int users_id, list_id; | |
326 | char *name; | |
327 | EXEC SQL END DECLARE SECTION; | |
328 | int status, client_id; | |
329 | char *client_type; | |
330 | ||
331 | name = argv[0]; | |
332 | EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys | |
333 | WHERE label = :name; | |
334 | ||
335 | if (sqlca.sqlerrd[2] != 1) | |
336 | return(MR_PERM); | |
337 | if (users_id == cl->users_id) | |
338 | return(MR_SUCCESS); | |
339 | if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) | |
340 | return(status); | |
341 | status = find_member("LIST", list_id, client_type, client_id, 0); | |
342 | if (status) | |
343 | return(MR_SUCCESS); | |
344 | else | |
345 | return(MR_PERM); | |
346 | } | |
347 | ||
1beb5e23 | 348 | |
349 | /* access_host - successful if owner of host, or subnet containing host | |
350 | */ | |
351 | ||
fc2f4a27 | 352 | int host_access_level = 0; /* 1 for network, 2 for host */ |
1beb5e23 | 353 | |
354 | access_host(q, argv, cl) | |
355 | struct query *q; | |
356 | char *argv[]; | |
357 | client *cl; | |
358 | { | |
359 | EXEC SQL BEGIN DECLARE SECTION; | |
360 | int mid, sid, users_id, id; | |
361 | char mtype[9], stype[9], *name; | |
362 | EXEC SQL END DECLARE SECTION; | |
363 | int status, client_id; | |
364 | char *client_type; | |
365 | ||
366 | if (q->type == APPEND) { | |
367 | id = *(int *)argv[8]; | |
368 | EXEC SQL SELECT s.owner_type, s.owner_id | |
369 | INTO :stype, :sid FROM subnet s | |
370 | WHERE s.snet_id=:id; | |
371 | mid =0; | |
372 | } else if (q->type == RETRIEVE) { | |
fc2f4a27 | 373 | return(MR_SUCCESS); |
1beb5e23 | 374 | } else { |
375 | id = *(int *)argv[0]; | |
376 | EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id | |
377 | INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s | |
378 | WHERE m.mach_id=:id and s.snet_id=m.snet_id; | |
379 | } | |
380 | if (sqlca.sqlerrd[2] != 1) | |
381 | return(MR_PERM); | |
382 | ||
383 | if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) | |
384 | return(status); | |
385 | status = find_member(stype, sid, client_type, client_id, 0); | |
386 | if (status) { | |
387 | host_access_level = 1; | |
388 | return(MR_SUCCESS); | |
389 | } | |
390 | status = find_member(mtype, mid, client_type, client_id, 0); | |
391 | if (status) { | |
392 | host_access_level = 2; | |
393 | return(MR_SUCCESS); | |
394 | } else | |
395 | return(MR_PERM); | |
396 | } | |
397 | ||
398 | ||
399 | /* access_ahal - check for adding a host alias. | |
400 | * successful if host has less then 2 aliases and (client is owner of | |
401 | * host or subnet). | |
402 | * If deleting an alias, any owner will do. | |
403 | */ | |
404 | ||
405 | access_ahal(q, argv, cl) | |
406 | struct query *q; | |
407 | char *argv[]; | |
408 | client *cl; | |
409 | { | |
410 | EXEC SQL BEGIN DECLARE SECTION; | |
411 | int cnt, id, mid, sid; | |
412 | char mtype[256], stype[256]; | |
413 | EXEC SQL END DECLARE SECTION; | |
414 | char *client_type; | |
415 | int status, client_id; | |
416 | ||
27343965 | 417 | if (q->type == RETRIEVE) |
418 | return(MR_SUCCESS); | |
419 | ||
1beb5e23 | 420 | id = *(int *)argv[1]; |
421 | ||
422 | EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id; | |
423 | if (ingres_errno) return(mr_errcode); | |
424 | /* if the type is APPEND, this is ahal and we need to make sure there | |
425 | * will be no more than 2 aliases. If it's not, it must be dhal and | |
426 | * any owner will do. | |
427 | */ | |
428 | if (q->type == APPEND && cnt >= 2) | |
429 | return(MR_PERM); | |
1beb5e23 | 430 | EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id |
431 | INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s | |
432 | WHERE m.mach_id=:id and s.snet_id=m.snet_id; | |
433 | if ((status = get_client(cl, &client_type, &client_id)) != MR_SUCCESS) | |
434 | return(status); | |
435 | status = find_member(mtype, mid, client_type, client_id, 0); | |
436 | if (status) | |
437 | return(MR_SUCCESS); | |
438 | status = find_member(stype, sid, client_type, client_id, 0); | |
439 | if (status) | |
440 | return(MR_SUCCESS); | |
441 | else | |
442 | return(MR_PERM); | |
443 | } | |
7cf83f0f | 444 | |
445 | ||
446 | ||
447 | /* access_snt - check for retrieving network structure | |
448 | */ | |
449 | ||
450 | access_snt(q, argv, cl) | |
451 | struct query *q; | |
452 | char *argv[]; | |
453 | client *cl; | |
454 | { | |
455 | if(q->type == RETRIEVE) | |
456 | return(MR_SUCCESS); | |
457 | ||
458 | return(MR_PERM); | |
459 | } |