]>
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 | ||
5eaef520 | 41 | int access_user(struct query *q, char *argv[], client *cl) |
73cf66ba | 42 | { |
5eaef520 | 43 | if (cl->users_id != *(int *)argv[0]) |
44 | return MR_PERM; | |
45 | else | |
46 | return MR_SUCCESS; | |
73cf66ba | 47 | } |
48 | ||
49 | ||
50 | ||
51 | /* access_login - verify that client name equals specified login name | |
52 | * | |
53 | * argv[0...n] contain search info. q-> | |
54 | */ | |
55 | ||
5eaef520 | 56 | int access_login(struct query *q, char *argv[], client *cl) |
73cf66ba | 57 | { |
5eaef520 | 58 | EXEC SQL BEGIN DECLARE SECTION; |
59 | int id; | |
60 | EXEC SQL END DECLARE SECTION; | |
73cf66ba | 61 | |
5eaef520 | 62 | if (q->argc != 1) |
63 | return MR_ARGS; | |
03c05291 | 64 | |
5eaef520 | 65 | if (!strcmp(q->shortname, "gual")) |
66 | { | |
5906749e | 67 | EXEC SQL SELECT users_id INTO :id FROM users |
68 | WHERE login LIKE :argv[0] AND users_id != 0; | |
5eaef520 | 69 | } |
70 | else if (!strcmp(q->shortname, "gubl")) | |
71 | { | |
03c05291 | 72 | EXEC SQL SELECT users_id INTO :id FROM users u |
73 | WHERE u.login LIKE :argv[0] AND u.users_id != 0; | |
5eaef520 | 74 | } |
75 | else if (!strcmp(q->shortname, "guau")) | |
76 | { | |
5906749e | 77 | EXEC SQL SELECT users_id INTO :id FROM users |
78 | WHERE unix_uid = :argv[0] AND users_id != 0; | |
5eaef520 | 79 | } |
80 | else if (!strcmp(q->shortname, "gubu")) | |
81 | { | |
03c05291 | 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 | ||
5eaef520 | 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) | |
90 | return MR_PERM; | |
91 | else | |
92 | return MR_SUCCESS; | |
73cf66ba | 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 | ||
5eaef520 | 110 | int access_list(struct query *q, char *argv[], client *cl) |
73cf66ba | 111 | { |
5eaef520 | 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; | |
116 | int status; | |
117 | ||
118 | list_id = *(int *)argv[0]; | |
119 | EXEC SQL SELECT acl_id, acl_type, gid, publicflg | |
120 | INTO :acl_id, :acl_type, :gid, :flags | |
121 | FROM list | |
122 | WHERE list_id = :list_id; | |
123 | ||
124 | if (sqlca.sqlerrd[2] != 1) | |
125 | return MR_INTERNAL; | |
126 | ||
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)))) | |
130 | { | |
131 | if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id) | |
132 | return MR_SUCCESS; | |
133 | if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id) | |
134 | return MR_SUCCESS; | |
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)) | |
138 | { | |
139 | if (!strcmp(argv[7], UNIQUE_GID)) | |
140 | { | |
141 | if (gid != -1) | |
142 | return MR_PERM; | |
143 | } | |
144 | else | |
145 | { | |
146 | if (gid != atoi(argv[7])) | |
147 | return MR_PERM; | |
148 | } | |
d83ee5a2 | 149 | newname = argv[1]; |
150 | EXEC SQL SELECT users_id INTO :users_id FROM users | |
5eaef520 | 151 | WHERE login = :newname; |
f3c08a60 | 152 | if ((sqlca.sqlcode != SQL_NO_MATCH) && (users_id != cl->users_id)) |
5eaef520 | 153 | return MR_PERM; |
73cf66ba | 154 | } |
155 | ||
5eaef520 | 156 | /* check for client in access control list */ |
157 | status = find_member(acl_type, acl_id, cl); | |
158 | if (!status) | |
159 | return MR_PERM; | |
73cf66ba | 160 | |
5eaef520 | 161 | return MR_SUCCESS; |
73cf66ba | 162 | } |
163 | ||
164 | ||
165 | /* access_visible_list - allow access to list only if it is not hidden, | |
166 | * or if the client is on the ACL | |
167 | * | |
168 | * Inputs: argv[0] - list_id | |
169 | * cl - client identifier | |
170 | */ | |
171 | ||
5eaef520 | 172 | int access_visible_list(struct query *q, char *argv[], client *cl) |
73cf66ba | 173 | { |
5eaef520 | 174 | EXEC SQL BEGIN DECLARE SECTION; |
175 | int list_id, acl_id, flags ; | |
176 | char acl_type[9]; | |
177 | EXEC SQL END DECLARE SECTION; | |
178 | int status; | |
179 | ||
180 | list_id = *(int *)argv[0]; | |
181 | EXEC SQL SELECT hidden, acl_id, acl_type | |
182 | INTO :flags, :acl_id, :acl_type | |
183 | FROM list | |
184 | WHERE list_id = :list_id; | |
185 | if (sqlca.sqlerrd[2] != 1) | |
186 | return MR_INTERNAL; | |
187 | if (!flags) | |
188 | return MR_SUCCESS; | |
189 | ||
190 | /* check for client in access control list */ | |
191 | status = find_member(acl_type, acl_id, cl); | |
192 | if (!status) | |
193 | return MR_PERM; | |
194 | ||
195 | return MR_SUCCESS; | |
73cf66ba | 196 | } |
197 | ||
198 | ||
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 | |
201 | * | |
202 | * Inputs: argv[0] - list name | |
203 | * cl - client identifier | |
204 | */ | |
205 | ||
5eaef520 | 206 | int access_vis_list_by_name(struct query *q, char *argv[], client *cl) |
73cf66ba | 207 | { |
5eaef520 | 208 | EXEC SQL BEGIN DECLARE SECTION; |
209 | int acl_id, flags, rowcount; | |
210 | char acl_type[9], *listname; | |
211 | EXEC SQL END DECLARE SECTION; | |
212 | int status; | |
213 | ||
214 | listname = argv[0]; | |
215 | EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type | |
216 | FROM list WHERE name = :listname; | |
217 | ||
218 | rowcount = sqlca.sqlerrd[2]; | |
219 | if (rowcount > 1) | |
220 | return MR_WILDCARD; | |
221 | if (rowcount == 0) | |
222 | return MR_NO_MATCH; | |
223 | if (!flags) | |
224 | return MR_SUCCESS; | |
225 | ||
226 | /* check for client in access control list */ | |
227 | status = find_member(acl_type, acl_id, cl); | |
228 | if (!status) | |
229 | return MR_PERM; | |
230 | ||
231 | return MR_SUCCESS; | |
73cf66ba | 232 | } |
233 | ||
234 | ||
235 | /* access_member - allow user to access member of type "USER" and name matches | |
f3c08a60 | 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 | |
73cf66ba | 238 | * on the acl of, or the list is visible. |
239 | */ | |
240 | ||
5eaef520 | 241 | int access_member(struct query *q, char *argv[], client *cl) |
73cf66ba | 242 | { |
5eaef520 | 243 | if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST")) |
244 | return access_visible_list(q, &argv[1], cl); | |
73cf66ba | 245 | |
5eaef520 | 246 | if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) |
247 | { | |
248 | if (cl->users_id == *(int *)argv[1]) | |
249 | return MR_SUCCESS; | |
73cf66ba | 250 | } |
251 | ||
5eaef520 | 252 | if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS")) |
253 | { | |
254 | if (cl->client_id == -*(int *)argv[1]) | |
255 | return MR_SUCCESS; | |
73cf66ba | 256 | } |
257 | ||
5eaef520 | 258 | return MR_PERM; |
73cf66ba | 259 | } |
260 | ||
261 | ||
262 | /* access_qgli - special access routine for Qualified_get_lists. Allows | |
263 | * access iff argv[0] == "TRUE" and argv[2] == "FALSE". | |
264 | */ | |
265 | ||
5eaef520 | 266 | int access_qgli(struct query *q, char *argv[], client *cl) |
73cf66ba | 267 | { |
5eaef520 | 268 | if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE")) |
269 | return MR_SUCCESS; | |
270 | return MR_PERM; | |
73cf66ba | 271 | } |
272 | ||
273 | ||
274 | /* access_service - allow access if user is on ACL of service. Don't | |
275 | * allow access if a wildcard is used. | |
276 | */ | |
277 | ||
5eaef520 | 278 | int access_service(struct query *q, char *argv[], client *cl) |
73cf66ba | 279 | { |
5eaef520 | 280 | EXEC SQL BEGIN DECLARE SECTION; |
281 | int acl_id; | |
282 | char *name, acl_type[9]; | |
283 | EXEC SQL END DECLARE SECTION; | |
284 | int status; | |
285 | char *c; | |
286 | ||
287 | name = argv[0]; | |
288 | for (c = name; *c; c++) | |
289 | { | |
290 | if (islower(*c)) | |
291 | *c = toupper(*c); | |
292 | } | |
293 | EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers | |
294 | WHERE name = :name; | |
295 | if (sqlca.sqlerrd[2] > 1) | |
296 | return MR_PERM; | |
297 | ||
298 | /* check for client in access control list */ | |
299 | status = find_member(acl_type, acl_id, cl); | |
300 | if (!status) | |
301 | return MR_PERM; | |
302 | ||
303 | return MR_SUCCESS; | |
73cf66ba | 304 | } |
305 | ||
306 | ||
307 | /* access_filesys - verify that client is owner or on owners list of filesystem | |
308 | * named by argv[0] | |
309 | */ | |
310 | ||
5eaef520 | 311 | int access_filesys(struct query *q, char *argv[], client *cl) |
73cf66ba | 312 | { |
5eaef520 | 313 | EXEC SQL BEGIN DECLARE SECTION; |
314 | int users_id, list_id; | |
315 | char *name; | |
316 | EXEC SQL END DECLARE SECTION; | |
317 | int status; | |
318 | ||
319 | name = argv[0]; | |
320 | EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys | |
321 | WHERE label = :name; | |
322 | ||
323 | if (sqlca.sqlerrd[2] != 1) | |
324 | return MR_PERM; | |
325 | if (users_id == cl->users_id) | |
326 | return MR_SUCCESS; | |
327 | status = find_member("LIST", list_id, cl); | |
328 | if (status) | |
329 | return MR_SUCCESS; | |
330 | else | |
331 | return MR_PERM; | |
73cf66ba | 332 | } |
333 | ||
1beb5e23 | 334 | |
335 | /* access_host - successful if owner of host, or subnet containing host | |
336 | */ | |
337 | ||
fc2f4a27 | 338 | int host_access_level = 0; /* 1 for network, 2 for host */ |
1beb5e23 | 339 | |
5eaef520 | 340 | int access_host(struct query *q, char *argv[], client *cl) |
1beb5e23 | 341 | { |
5eaef520 | 342 | EXEC SQL BEGIN DECLARE SECTION; |
343 | int mid, sid, id; | |
344 | char mtype[9], stype[9]; | |
345 | EXEC SQL END DECLARE SECTION; | |
346 | int status; | |
347 | ||
348 | if (q->type == APPEND) | |
349 | { | |
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; | |
354 | mid = 0; | |
1beb5e23 | 355 | } |
5eaef520 | 356 | else if (q->type == RETRIEVE) |
357 | { | |
358 | if (strcmp(argv[0], "*") || strcmp(argv[1], "*") || | |
359 | strcmp(argv[2], "*") || strcmp(argv[3], "*")) | |
360 | return MR_SUCCESS; | |
361 | else | |
362 | return MR_PERM; | |
363 | } | |
364 | else | |
365 | { | |
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; | |
370 | } | |
371 | if (sqlca.sqlerrd[2] != 1) | |
372 | return MR_PERM; | |
373 | ||
374 | status = find_member(stype, sid, cl); | |
375 | if (status) | |
376 | { | |
377 | host_access_level = 1; | |
378 | return MR_SUCCESS; | |
379 | } | |
380 | status = find_member(mtype, mid, cl); | |
381 | if (status) | |
382 | { | |
383 | host_access_level = 2; | |
384 | return MR_SUCCESS; | |
1beb5e23 | 385 | } |
5eaef520 | 386 | else |
387 | return MR_PERM; | |
1beb5e23 | 388 | } |
389 | ||
390 | ||
391 | /* access_ahal - check for adding a host alias. | |
392 | * successful if host has less then 2 aliases and (client is owner of | |
393 | * host or subnet). | |
394 | * If deleting an alias, any owner will do. | |
395 | */ | |
396 | ||
5eaef520 | 397 | int access_ahal(struct query *q, char *argv[], client *cl) |
1beb5e23 | 398 | { |
5eaef520 | 399 | EXEC SQL BEGIN DECLARE SECTION; |
400 | int cnt, id, mid, sid; | |
401 | char mtype[256], stype[256]; | |
402 | EXEC SQL END DECLARE SECTION; | |
403 | int status; | |
404 | ||
405 | if (q->type == RETRIEVE) | |
406 | return MR_SUCCESS; | |
407 | ||
408 | id = *(int *)argv[1]; | |
409 | ||
410 | EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id; | |
411 | if (dbms_errno) | |
412 | return mr_errcode; | |
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 | |
415 | * any owner will do. | |
416 | */ | |
417 | if (q->type == APPEND && cnt >= 2) | |
418 | return MR_PERM; | |
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); | |
423 | if (status) | |
424 | return MR_SUCCESS; | |
425 | status = find_member(stype, sid, cl); | |
426 | if (status) | |
427 | return MR_SUCCESS; | |
428 | else | |
429 | return MR_PERM; | |
1beb5e23 | 430 | } |
7cf83f0f | 431 | |
432 | ||
433 | ||
434 | /* access_snt - check for retrieving network structure | |
435 | */ | |
436 | ||
5eaef520 | 437 | int access_snt(struct query *q, char *argv[], client *cl) |
7cf83f0f | 438 | { |
5eaef520 | 439 | if (q->type == RETRIEVE) |
440 | return MR_SUCCESS; | |
7cf83f0f | 441 | |
5eaef520 | 442 | return MR_PERM; |
7cf83f0f | 443 | } |