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