]>
Commit | Line | Data |
---|---|---|
7ac48069 | 1 | /* $Id$ |
73cf66ba | 2 | * |
7ac48069 | 3 | * Check access to queries |
73cf66ba | 4 | * |
7ac48069 | 5 | * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
73cf66ba | 8 | */ |
9 | ||
73cf66ba | 10 | #include <mit-copyright.h> |
73cf66ba | 11 | #include "mr_server.h" |
7ac48069 | 12 | #include "qrtn.h" |
03c05291 | 13 | #include "query.h" |
7ac48069 | 14 | |
73cf66ba | 15 | #include <ctype.h> |
7ac48069 | 16 | #include <stdlib.h> |
17 | ||
73cf66ba | 18 | EXEC SQL INCLUDE sqlca; |
7ac48069 | 19 | |
20 | RCSID("$Header$"); | |
73cf66ba | 21 | |
22 | extern char *whoami; | |
03c05291 | 23 | extern int dbms_errno, mr_errcode; |
73cf66ba | 24 | |
03c05291 | 25 | EXEC SQL WHENEVER SQLERROR DO dbmserr(); |
73cf66ba | 26 | |
27 | ||
28 | /* Specialized Access Routines */ | |
29 | ||
30 | /* access_user - verify that client name equals specified login name | |
31 | * | |
32 | * - since field validation routines are called first, a users_id is | |
33 | * now in argv[0] instead of the login name. | |
34 | */ | |
35 | ||
5eaef520 | 36 | int access_user(struct query *q, char *argv[], client *cl) |
73cf66ba | 37 | { |
5eaef520 | 38 | if (cl->users_id != *(int *)argv[0]) |
39 | return MR_PERM; | |
40 | else | |
41 | return MR_SUCCESS; | |
73cf66ba | 42 | } |
43 | ||
34b6375c | 44 | int access_update_user(struct query *q, char *argv[], client *cl) |
45 | { | |
46 | EXEC SQL BEGIN DECLARE SECTION; | |
47 | int users_id, unix_uid, status, comments, secure; | |
48 | char login[USERS_LOGIN_SIZE], shell[USERS_SHELL_SIZE]; | |
49 | char winconsoleshell[USERS_WINCONSOLESHELL_SIZE], last[USERS_LAST_SIZE]; | |
50 | char first[USERS_FIRST_SIZE], middle[USERS_MIDDLE_SIZE]; | |
51 | char clearid[USERS_CLEARID_SIZE], type[USERS_TYPE_SIZE]; | |
52 | char signature[USERS_SIGNATURE_SIZE]; | |
53 | EXEC SQL END DECLARE SECTION; | |
73cf66ba | 54 | |
34b6375c | 55 | /* The two fields we let users update themselves didn't appear until |
56 | * version 11. | |
57 | */ | |
58 | if (q->version < 11) | |
59 | return MR_PERM; | |
60 | ||
61 | if (cl->users_id != *(int *)argv[0]) | |
62 | return MR_PERM; | |
63 | ||
64 | users_id = *(int *)argv[0]; | |
65 | ||
66 | EXEC SQL SELECT u.login, u.unix_uid, u.shell, u.winconsoleshell, u.last, | |
67 | u.first, u.middle, u.status, u.clearid, u.type, u.comments, u.signature, | |
68 | u.secure INTO :login, :unix_uid, :shell, :winconsoleshell, :last, :first, | |
69 | :middle, :status, :clearid, :type, :comments, :signature, :secure | |
70 | FROM USERS u WHERE u.users_id = :users_id; | |
71 | ||
72 | /* None of these things can have changed. */ | |
73 | if (strcmp(argv[1], strtrim(login)) || | |
74 | (unix_uid != atoi(argv[2])) || | |
75 | strcmp(argv[3], strtrim(shell)) || | |
76 | strcmp(argv[4], strtrim(winconsoleshell)) || | |
77 | strcmp(argv[5], strtrim(last)) || | |
78 | strcmp(argv[6], strtrim(first)) || | |
79 | strcmp(argv[7], strtrim(middle)) || | |
80 | (status != atoi(argv[8])) || | |
81 | strcmp(argv[9], strtrim(clearid)) || | |
82 | strcmp(argv[10], strtrim(type)) || | |
83 | (comments != *(int *)argv[11]) || | |
84 | strcmp(argv[12], strtrim(signature)) || | |
85 | (secure != atoi(argv[13]))) | |
86 | return MR_PERM; | |
87 | ||
88 | return MR_SUCCESS; | |
89 | } | |
73cf66ba | 90 | |
91 | /* access_login - verify that client name equals specified login name | |
92 | * | |
93 | * argv[0...n] contain search info. q-> | |
94 | */ | |
95 | ||
5eaef520 | 96 | int access_login(struct query *q, char *argv[], client *cl) |
73cf66ba | 97 | { |
5eaef520 | 98 | EXEC SQL BEGIN DECLARE SECTION; |
99 | int id; | |
100 | EXEC SQL END DECLARE SECTION; | |
73cf66ba | 101 | |
5eaef520 | 102 | if (q->argc != 1) |
103 | return MR_ARGS; | |
03c05291 | 104 | |
5eaef520 | 105 | if (!strcmp(q->shortname, "gual")) |
106 | { | |
5906749e | 107 | EXEC SQL SELECT users_id INTO :id FROM users |
cc0ec904 | 108 | WHERE login = :argv[0] AND users_id != 0; |
5eaef520 | 109 | } |
110 | else if (!strcmp(q->shortname, "gubl")) | |
111 | { | |
03c05291 | 112 | EXEC SQL SELECT users_id INTO :id FROM users u |
cc0ec904 | 113 | WHERE u.login = :argv[0] AND u.users_id != 0; |
5eaef520 | 114 | } |
115 | else if (!strcmp(q->shortname, "guau")) | |
116 | { | |
5906749e | 117 | EXEC SQL SELECT users_id INTO :id FROM users |
118 | WHERE unix_uid = :argv[0] AND users_id != 0; | |
5eaef520 | 119 | } |
120 | else if (!strcmp(q->shortname, "gubu")) | |
121 | { | |
03c05291 | 122 | EXEC SQL SELECT users_id INTO :id FROM users u |
123 | WHERE u.unix_uid = :argv[0] AND u.users_id != 0; | |
73cf66ba | 124 | } |
125 | ||
5eaef520 | 126 | if (sqlca.sqlcode == SQL_NO_MATCH) |
127 | return MR_NO_MATCH; /* ought to be MR_USER, but this is what | |
128 | gual returns, so we have to be consistent */ | |
129 | else if (sqlca.sqlerrd[2] != 1 || id != cl->users_id) | |
130 | return MR_PERM; | |
131 | else | |
132 | return MR_SUCCESS; | |
73cf66ba | 133 | } |
134 | ||
135 | ||
f659afb2 | 136 | /* access_spob - check access for set_pobox */ |
137 | ||
138 | int access_spob(struct query *q, char *argv[], client *cl) | |
139 | { | |
51e578b6 | 140 | EXEC SQL BEGIN DECLARE SECTION; |
141 | int id; | |
142 | EXEC SQL END DECLARE SECTION; | |
143 | ||
144 | if (!strcmp(argv[1], "IMAP")) | |
145 | { | |
146 | EXEC SQL SELECT owner INTO :id FROM filesys f | |
147 | WHERE f.label = :argv[2] AND f.type = 'IMAP' AND | |
148 | f.lockertype = 'USER'; | |
149 | if (cl->users_id != id) | |
150 | return MR_PERM; | |
151 | } | |
152 | if (cl->users_id != *(int *)argv[0]) | |
f659afb2 | 153 | return MR_PERM; |
154 | else | |
155 | return MR_SUCCESS; | |
156 | } | |
157 | ||
73cf66ba | 158 | |
159 | /* access_list - check access for most list operations | |
160 | * | |
161 | * Inputs: argv[0] - list_id | |
162 | * q - query name | |
163 | * argv[2] - member ID (only for queries "amtl" and "dmfl") | |
e688520a | 164 | * argv[7] - group ID (only for query "ulis") |
73cf66ba | 165 | * cl - client name |
166 | * | |
167 | * - check that client is a member of the access control list | |
168 | * - OR, if the query is add_member_to_list or delete_member_from_list | |
169 | * and the list is public, allow access if client = member | |
170 | */ | |
171 | ||
5eaef520 | 172 | int access_list(struct query *q, char *argv[], client *cl) |
73cf66ba | 173 | { |
5eaef520 | 174 | EXEC SQL BEGIN DECLARE SECTION; |
40b33762 | 175 | int list_id, acl_id, flags, gid, users_id, member_id, member_acl_id; |
8e3761a2 | 176 | int memacl_id, mailman, mailman_id; |
e688520a | 177 | char acl_type[LIST_ACL_TYPE_SIZE], name[LIST_NAME_SIZE], *newname; |
59c3208b | 178 | char member_acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; |
5eaef520 | 179 | EXEC SQL END DECLARE SECTION; |
8e3761a2 | 180 | int status, cnt; |
5eaef520 | 181 | |
182 | list_id = *(int *)argv[0]; | |
40b33762 | 183 | member_id = *(int *)argv[2]; |
59c3208b | 184 | EXEC SQL SELECT acl_id, acl_type, memacl_id, memacl_type, |
8e3761a2 | 185 | gid, publicflg, name, mailman, mailman_id |
59c3208b | 186 | INTO :acl_id, :acl_type, :memacl_id, :memacl_type, |
8e3761a2 | 187 | :gid, :flags, :name, :mailman, :mailman_id |
5eaef520 | 188 | FROM list |
189 | WHERE list_id = :list_id; | |
190 | ||
191 | if (sqlca.sqlerrd[2] != 1) | |
192 | return MR_INTERNAL; | |
193 | ||
59c3208b | 194 | /* if update_list, don't allow them to change the GID or rename to a |
195 | username other than their own */ | |
196 | if (!strcmp("ulis", q->shortname)) | |
5eaef520 | 197 | { |
198 | if (!strcmp(argv[7], UNIQUE_GID)) | |
199 | { | |
200 | if (gid != -1) | |
201 | return MR_PERM; | |
202 | } | |
203 | else | |
204 | { | |
205 | if (gid != atoi(argv[7])) | |
206 | return MR_PERM; | |
207 | } | |
5c96d2cd | 208 | |
d83ee5a2 | 209 | newname = argv[1]; |
5c96d2cd | 210 | |
8e3761a2 | 211 | /* Check that it doesn't conflict with the Grouper namespace. */ |
212 | if (strlen(newname) > 4 && isdigit(newname[2]) && | |
213 | isdigit(newname[3]) && newname[4] == '-') | |
214 | { | |
215 | if (!strncasecmp(newname, "fa", 2) || | |
216 | !strncasecmp(newname, "sp", 2) || | |
217 | !strncasecmp(newname, "su", 2) || | |
218 | !strncasecmp(newname, "ja", 2)) | |
219 | return MR_RESERVED; | |
220 | } | |
221 | ||
222 | /* Don't let anyone take owner-foo list names. They interact | |
223 | * weirdly with the aliases automatically generated by | |
224 | * mailhub.gen. | |
225 | */ | |
226 | if (!strncasecmp(newname, "owner-", 6)) | |
227 | return MR_RESERVED; | |
228 | ||
d83ee5a2 | 229 | EXEC SQL SELECT users_id INTO :users_id FROM users |
5eaef520 | 230 | WHERE login = :newname; |
17f090e1 | 231 | if ((sqlca.sqlcode != SQL_NO_MATCH) && strcmp(strtrim(name), newname) && |
232 | (users_id != cl->users_id)) | |
5eaef520 | 233 | return MR_PERM; |
8e3761a2 | 234 | |
235 | /* For modern enough clients, don't allow ordinary users to toggle | |
236 | * the mailman bit or change the server. | |
237 | */ | |
238 | if (q->version >= 10) | |
239 | { | |
240 | if (mailman != atoi(argv[9])) | |
241 | return MR_PERM; | |
242 | ||
243 | if (mailman_id != *(int *)argv[10]) | |
244 | return MR_PERM; | |
245 | } | |
73cf66ba | 246 | } |
247 | ||
59c3208b | 248 | /* check for client in access control list and return success right |
249 | * away if it's there. */ | |
250 | if (find_member(acl_type, acl_id, cl)) | |
251 | return MR_SUCCESS; | |
252 | ||
253 | /* If not amtl, atml, or dmfl, we lose. */ | |
254 | if (strcmp(q->shortname, "amtl") && strcmp(q->shortname, "atml") && | |
e3fbe284 | 255 | strcmp(q->shortname, "dmfl") && strcmp(q->shortname, "tmol")) |
5eaef520 | 256 | return MR_PERM; |
73cf66ba | 257 | |
59c3208b | 258 | if (find_member(memacl_type, memacl_id, cl)) |
259 | return MR_SUCCESS; | |
260 | ||
261 | if (flags || q->type == DELETE) | |
262 | { | |
263 | if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id) | |
264 | return MR_SUCCESS; | |
265 | if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id) | |
266 | return MR_SUCCESS; | |
267 | if (!strcmp("LIST", argv[1]) && !strcmp("dmfl", q->shortname)) | |
268 | { | |
269 | EXEC SQL SELECT acl_id, acl_type INTO :member_acl_id, | |
270 | :member_acl_type | |
271 | FROM list | |
272 | WHERE list_id = :member_id; | |
273 | ||
274 | if (find_member(member_acl_type, member_acl_id, cl)) | |
275 | return MR_SUCCESS; | |
276 | } | |
277 | } | |
278 | ||
279 | /* Otherwise fail. */ | |
280 | return MR_PERM; | |
73cf66ba | 281 | } |
282 | ||
283 | ||
284 | /* access_visible_list - allow access to list only if it is not hidden, | |
285 | * or if the client is on the ACL | |
286 | * | |
287 | * Inputs: argv[0] - list_id | |
288 | * cl - client identifier | |
289 | */ | |
290 | ||
5eaef520 | 291 | int access_visible_list(struct query *q, char *argv[], client *cl) |
73cf66ba | 292 | { |
5eaef520 | 293 | EXEC SQL BEGIN DECLARE SECTION; |
59c3208b | 294 | int list_id, acl_id, memacl_id, flags ; |
295 | char acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; | |
5eaef520 | 296 | EXEC SQL END DECLARE SECTION; |
297 | int status; | |
298 | ||
299 | list_id = *(int *)argv[0]; | |
59c3208b | 300 | EXEC SQL SELECT hidden, acl_id, acl_type, memacl_id, memacl_type |
301 | INTO :flags, :acl_id, :acl_type, :memacl_id, :memacl_type | |
5eaef520 | 302 | FROM list |
303 | WHERE list_id = :list_id; | |
304 | if (sqlca.sqlerrd[2] != 1) | |
305 | return MR_INTERNAL; | |
306 | if (!flags) | |
307 | return MR_SUCCESS; | |
308 | ||
309 | /* check for client in access control list */ | |
310 | status = find_member(acl_type, acl_id, cl); | |
311 | if (!status) | |
59c3208b | 312 | { |
313 | status = find_member(memacl_type, memacl_id, cl); | |
314 | if (!status) | |
315 | return MR_PERM; | |
316 | } | |
5eaef520 | 317 | return MR_SUCCESS; |
73cf66ba | 318 | } |
319 | ||
320 | ||
321 | /* access_vis_list_by_name - allow access to list only if it is not hidden, | |
322 | * or if the client is on the ACL | |
323 | * | |
324 | * Inputs: argv[0] - list name | |
325 | * cl - client identifier | |
326 | */ | |
327 | ||
5eaef520 | 328 | int access_vis_list_by_name(struct query *q, char *argv[], client *cl) |
73cf66ba | 329 | { |
5eaef520 | 330 | EXEC SQL BEGIN DECLARE SECTION; |
2affa9d4 | 331 | int acl_id, memacl_id, flags, rowcount, list_id; |
59c3208b | 332 | char acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE]; |
333 | char *listname; | |
5eaef520 | 334 | EXEC SQL END DECLARE SECTION; |
335 | int status; | |
336 | ||
337 | listname = argv[0]; | |
2affa9d4 | 338 | EXEC SQL SELECT hidden, acl_id, acl_type, memacl_id, memacl_type, list_id |
339 | INTO :flags, :acl_id, :acl_type, :memacl_id, :memacl_type, :list_id | |
59c3208b | 340 | FROM list |
341 | WHERE name = :listname; | |
5eaef520 | 342 | |
343 | rowcount = sqlca.sqlerrd[2]; | |
344 | if (rowcount > 1) | |
345 | return MR_WILDCARD; | |
346 | if (rowcount == 0) | |
347 | return MR_NO_MATCH; | |
348 | if (!flags) | |
349 | return MR_SUCCESS; | |
350 | ||
2affa9d4 | 351 | /* If the user is a member of the acl, memacl, or the list itself, |
352 | * accept them. | |
353 | */ | |
5eaef520 | 354 | status = find_member(acl_type, acl_id, cl); |
355 | if (!status) | |
2affa9d4 | 356 | status = find_member(memacl_type, memacl_id, cl); |
357 | if (!status) | |
358 | status = find_member("LIST", list_id, cl); | |
359 | if (!status) | |
360 | return MR_PERM; | |
361 | ||
5eaef520 | 362 | return MR_SUCCESS; |
73cf66ba | 363 | } |
364 | ||
365 | ||
366 | /* access_member - allow user to access member of type "USER" and name matches | |
f3c08a60 | 367 | * username, or to access member of type "KERBEROS" and the principal matches |
368 | * the user, or to access member of type "LIST" and list is one that user is | |
d1d964a0 | 369 | * on the acl of, or the list is visible. Allow anyone to look up list |
370 | * memberships of MACHINEs. | |
73cf66ba | 371 | */ |
372 | ||
5eaef520 | 373 | int access_member(struct query *q, char *argv[], client *cl) |
73cf66ba | 374 | { |
5eaef520 | 375 | if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST")) |
376 | return access_visible_list(q, &argv[1], cl); | |
73cf66ba | 377 | |
5eaef520 | 378 | if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER")) |
379 | { | |
380 | if (cl->users_id == *(int *)argv[1]) | |
381 | return MR_SUCCESS; | |
73cf66ba | 382 | } |
383 | ||
5eaef520 | 384 | if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS")) |
385 | { | |
386 | if (cl->client_id == -*(int *)argv[1]) | |
387 | return MR_SUCCESS; | |
73cf66ba | 388 | } |
389 | ||
d1d964a0 | 390 | if (!strcmp(argv[0], "MACHINE") || !strcmp(argv[0], "RMACHINE")) |
391 | return MR_SUCCESS; | |
392 | ||
5eaef520 | 393 | return MR_PERM; |
73cf66ba | 394 | } |
395 | ||
396 | ||
397 | /* access_qgli - special access routine for Qualified_get_lists. Allows | |
398 | * access iff argv[0] == "TRUE" and argv[2] == "FALSE". | |
399 | */ | |
400 | ||
5eaef520 | 401 | int access_qgli(struct query *q, char *argv[], client *cl) |
73cf66ba | 402 | { |
5eaef520 | 403 | if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE")) |
404 | return MR_SUCCESS; | |
405 | return MR_PERM; | |
73cf66ba | 406 | } |
407 | ||
408 | ||
409 | /* access_service - allow access if user is on ACL of service. Don't | |
410 | * allow access if a wildcard is used. | |
411 | */ | |
412 | ||
5eaef520 | 413 | int access_service(struct query *q, char *argv[], client *cl) |
73cf66ba | 414 | { |
5eaef520 | 415 | EXEC SQL BEGIN DECLARE SECTION; |
416 | int acl_id; | |
e688520a | 417 | char *name, acl_type[LIST_ACL_TYPE_SIZE]; |
5eaef520 | 418 | EXEC SQL END DECLARE SECTION; |
419 | int status; | |
420 | char *c; | |
421 | ||
422 | name = argv[0]; | |
423 | for (c = name; *c; c++) | |
424 | { | |
425 | if (islower(*c)) | |
426 | *c = toupper(*c); | |
427 | } | |
428 | EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers | |
429 | WHERE name = :name; | |
430 | if (sqlca.sqlerrd[2] > 1) | |
431 | return MR_PERM; | |
432 | ||
433 | /* check for client in access control list */ | |
434 | status = find_member(acl_type, acl_id, cl); | |
435 | if (!status) | |
436 | return MR_PERM; | |
437 | ||
438 | return MR_SUCCESS; | |
73cf66ba | 439 | } |
440 | ||
441 | ||
442 | /* access_filesys - verify that client is owner or on owners list of filesystem | |
443 | * named by argv[0] | |
444 | */ | |
445 | ||
5eaef520 | 446 | int access_filesys(struct query *q, char *argv[], client *cl) |
73cf66ba | 447 | { |
5eaef520 | 448 | EXEC SQL BEGIN DECLARE SECTION; |
449 | int users_id, list_id; | |
450 | char *name; | |
451 | EXEC SQL END DECLARE SECTION; | |
452 | int status; | |
453 | ||
454 | name = argv[0]; | |
455 | EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys | |
456 | WHERE label = :name; | |
457 | ||
458 | if (sqlca.sqlerrd[2] != 1) | |
459 | return MR_PERM; | |
460 | if (users_id == cl->users_id) | |
461 | return MR_SUCCESS; | |
462 | status = find_member("LIST", list_id, cl); | |
463 | if (status) | |
464 | return MR_SUCCESS; | |
465 | else | |
466 | return MR_PERM; | |
73cf66ba | 467 | } |
468 | ||
1beb5e23 | 469 | |
470 | /* access_host - successful if owner of host, or subnet containing host | |
471 | */ | |
472 | ||
5eaef520 | 473 | int access_host(struct query *q, char *argv[], client *cl) |
1beb5e23 | 474 | { |
5eaef520 | 475 | EXEC SQL BEGIN DECLARE SECTION; |
4f6b1a05 | 476 | int mid, sid, id, subnet_status; |
e688520a | 477 | char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE]; |
4f6b1a05 | 478 | char *account_number; |
5eaef520 | 479 | EXEC SQL END DECLARE SECTION; |
e4ae0190 | 480 | int status, idx; |
481 | ||
482 | if (q->version < 6) | |
483 | idx = 0; | |
4f6b1a05 | 484 | else if (q->version >= 6 && q->version < 8) |
e4ae0190 | 485 | idx = 1; |
4f6b1a05 | 486 | else |
487 | idx = 2; | |
488 | ||
5eaef520 | 489 | if (q->type == APPEND) |
490 | { | |
17f090e1 | 491 | /* Non-query owner must set use to zero */ |
e4ae0190 | 492 | if (atoi(argv[6 + idx]) != 0) |
17f090e1 | 493 | return MR_PERM; |
494 | ||
9e252e6f | 495 | /* ... and start the hostname with a letter */ |
496 | if (isdigit(argv[0][0])) | |
497 | return MR_BAD_CHAR; | |
498 | ||
e4ae0190 | 499 | id = *(int *)argv[8 + idx]; |
4f6b1a05 | 500 | EXEC SQL SELECT s.owner_type, s.owner_id, s.status |
501 | INTO :stype, :sid, :subnet_status FROM subnet s | |
5eaef520 | 502 | WHERE s.snet_id = :id; |
503 | mid = 0; | |
17f090e1 | 504 | |
4f6b1a05 | 505 | /* Non query owner must provide valid billing information. */ |
506 | if (q->version >= 8) | |
507 | { | |
508 | if (subnet_status == SNET_STATUS_BILLABLE) | |
509 | { | |
510 | account_number = argv[7]; | |
511 | EXEC SQL SELECT account_number FROM accountnumbers | |
512 | WHERE account_number = :account_number; | |
513 | if (sqlca.sqlcode == SQL_NO_MATCH) | |
514 | return MR_ACCOUNT_NUMBER; | |
515 | } | |
516 | } | |
517 | ||
17f090e1 | 518 | if (find_member(stype, sid, cl)) |
5eaef520 | 519 | return MR_SUCCESS; |
520 | else | |
521 | return MR_PERM; | |
522 | } | |
17f090e1 | 523 | else /* q-type == UPDATE */ |
5eaef520 | 524 | { |
17f090e1 | 525 | EXEC SQL BEGIN DECLARE SECTION; |
526 | int status, acomment, use, ocomment, snid; | |
e688520a | 527 | char contact[MACHINE_CONTACT_SIZE], address[MACHINE_ADDRESS_SIZE]; |
9e252e6f | 528 | char name[MACHINE_NAME_SIZE]; |
e4ae0190 | 529 | char billing_contact[MACHINE_BILLING_CONTACT_SIZE]; |
17f090e1 | 530 | EXEC SQL END DECLARE SECTION; |
531 | ||
5eaef520 | 532 | id = *(int *)argv[0]; |
e4ae0190 | 533 | EXEC SQL SELECT m.name, m.use, m.contact, m.billing_contact, m.status, |
534 | m.address, m.owner_type, m.owner_id, m.acomment, m.ocomment, m.snet_id, | |
4f6b1a05 | 535 | s.owner_type, s.owner_id, s.status INTO :name, :use, :contact, |
536 | :billing_contact, :status, :address, :mtype, :mid, :acomment, | |
537 | :ocomment, :snid, :stype, :sid, :subnet_status | |
17f090e1 | 538 | FROM machine m, subnet s |
539 | WHERE m.mach_id = :id AND s.snet_id = m.snet_id; | |
540 | if (dbms_errno) | |
541 | return mr_errcode; | |
542 | ||
4f6b1a05 | 543 | /* Non query owner must provide valid billing information. */ |
544 | if (q->version >= 8) | |
545 | { | |
c862fa4e | 546 | if ((subnet_status == SNET_STATUS_BILLABLE) && |
547 | (atoi(argv[10]) != 3)) | |
4f6b1a05 | 548 | { |
549 | account_number = argv[8]; | |
550 | EXEC SQL SELECT account_number FROM accountnumbers | |
551 | WHERE account_number = :account_number; | |
552 | if (sqlca.sqlcode == SQL_NO_MATCH) | |
553 | return MR_ACCOUNT_NUMBER; | |
554 | } | |
555 | } | |
556 | ||
17f090e1 | 557 | /* non-query-owner cannot change use or ocomment */ |
e4ae0190 | 558 | if ((use != atoi(argv[7 + idx])) || (ocomment != *(int *)argv[14 + idx])) |
17f090e1 | 559 | return MR_PERM; |
560 | ||
9e252e6f | 561 | /* or rename to start with digit */ |
562 | if (isdigit(argv[1][0]) && strcmp(strtrim(name), argv[1])) | |
563 | return MR_BAD_CHAR; | |
564 | ||
17f090e1 | 565 | if (!find_member(stype, sid, cl)) |
566 | { | |
567 | if (find_member(mtype, mid, cl)) | |
568 | { | |
569 | /* host owner also cannot change contact, status, address, | |
570 | owner, or acomment */ | |
7617c632 | 571 | if (strcmp(argv[6], strtrim(contact)) || |
e4ae0190 | 572 | (status != atoi(argv[8 + idx])) || |
573 | strcmp(argv[10 + idx], strtrim(address)) || | |
574 | strcmp(argv[11 + idx], strtrim(mtype)) || | |
575 | (mid != *(int *)argv[12 + idx]) || | |
576 | (acomment != *(int *)argv[13 + idx])) | |
17f090e1 | 577 | return MR_PERM; |
e4ae0190 | 578 | /* Billing contact field didn't appear until version 6 */ |
579 | if (q->version >= 6) | |
7617c632 | 580 | if (strcmp(argv[7], strtrim(billing_contact))) |
e4ae0190 | 581 | return MR_PERM; |
17f090e1 | 582 | } |
583 | else | |
584 | return MR_PERM; | |
585 | } | |
586 | ||
587 | /* If moving to a new subnet, make sure user is on acl there */ | |
e4ae0190 | 588 | id = *(int *)argv[9 + idx]; |
17f090e1 | 589 | if (id != snid) |
590 | { | |
591 | EXEC SQL SELECT owner_type, owner_id INTO :stype, :sid | |
592 | FROM subnet WHERE snet_id=:id; | |
593 | if (!find_member(stype, sid, cl)) | |
594 | return MR_PERM; | |
595 | } | |
5eaef520 | 596 | |
5eaef520 | 597 | return MR_SUCCESS; |
1beb5e23 | 598 | } |
1beb5e23 | 599 | } |
600 | ||
601 | ||
602 | /* access_ahal - check for adding a host alias. | |
603 | * successful if host has less then 2 aliases and (client is owner of | |
604 | * host or subnet). | |
605 | * If deleting an alias, any owner will do. | |
606 | */ | |
607 | ||
5eaef520 | 608 | int access_ahal(struct query *q, char *argv[], client *cl) |
1beb5e23 | 609 | { |
5eaef520 | 610 | EXEC SQL BEGIN DECLARE SECTION; |
611 | int cnt, id, mid, sid; | |
e688520a | 612 | char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE]; |
5eaef520 | 613 | EXEC SQL END DECLARE SECTION; |
614 | int status; | |
615 | ||
616 | if (q->type == RETRIEVE) | |
617 | return MR_SUCCESS; | |
618 | ||
619 | id = *(int *)argv[1]; | |
620 | ||
9e252e6f | 621 | if (q->type == APPEND && isdigit(argv[0][0])) |
622 | return MR_BAD_CHAR; | |
623 | ||
5eaef520 | 624 | EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id; |
625 | if (dbms_errno) | |
626 | return mr_errcode; | |
627 | /* if the type is APPEND, this is ahal and we need to make sure there | |
628 | * will be no more than 2 aliases. If it's not, it must be dhal and | |
629 | * any owner will do. | |
630 | */ | |
631 | if (q->type == APPEND && cnt >= 2) | |
632 | return MR_PERM; | |
633 | EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id | |
634 | INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s | |
635 | WHERE m.mach_id = :id and s.snet_id = m.snet_id; | |
636 | status = find_member(mtype, mid, cl); | |
637 | if (status) | |
638 | return MR_SUCCESS; | |
639 | status = find_member(stype, sid, cl); | |
640 | if (status) | |
641 | return MR_SUCCESS; | |
642 | else | |
643 | return MR_PERM; | |
1beb5e23 | 644 | } |
7cf83f0f | 645 | |
646 | ||
7cf83f0f | 647 | /* access_snt - check for retrieving network structure |
648 | */ | |
649 | ||
5eaef520 | 650 | int access_snt(struct query *q, char *argv[], client *cl) |
7cf83f0f | 651 | { |
5eaef520 | 652 | if (q->type == RETRIEVE) |
653 | return MR_SUCCESS; | |
7cf83f0f | 654 | |
5eaef520 | 655 | return MR_PERM; |
7cf83f0f | 656 | } |
1a9a0a59 | 657 | |
658 | ||
659 | /* access_printer */ | |
660 | int access_printer(struct query *q, char *argv[], client *cl) | |
661 | { | |
662 | EXEC SQL BEGIN DECLARE SECTION; | |
663 | char type[PRINTSERVERS_OWNER_TYPE_SIZE]; | |
664 | int id, mach_id; | |
665 | EXEC SQL END DECLARE SECTION; | |
666 | int status; | |
667 | ||
668 | mach_id = *(int *)argv[PRN_RM]; | |
669 | EXEC SQL SELECT owner_type, owner_id INTO :type, :id | |
670 | FROM printservers WHERE mach_id = :mach_id; | |
671 | if (sqlca.sqlcode) | |
672 | return MR_PERM; | |
673 | ||
674 | status = find_member(type, id, cl); | |
675 | if (status) | |
676 | return MR_SUCCESS; | |
677 | else | |
678 | return MR_PERM; | |
679 | } | |
d7ddc011 | 680 | |
681 | /* access_zephyr */ | |
682 | int access_zephyr(struct query *q, char *argv[], client *cl) | |
683 | { | |
684 | EXEC SQL BEGIN DECLARE SECTION; | |
685 | char type[ZEPHYR_OWNER_TYPE_SIZE]; | |
686 | char *class; | |
687 | int id; | |
688 | EXEC SQL END DECLARE SECTION; | |
689 | int status; | |
690 | ||
691 | class = argv[ZA_CLASS]; | |
692 | EXEC SQL SELECT owner_type, owner_id INTO :type, :id | |
693 | FROM zephyr WHERE class = :class; | |
694 | if (sqlca.sqlcode) | |
695 | return MR_PERM; | |
696 | ||
697 | status = find_member(type, id, cl); | |
698 | if (status) | |
699 | return MR_SUCCESS; | |
700 | else | |
701 | return MR_PERM; | |
702 | } | |
703 | ||
2fb668b0 | 704 | /* access_container - check access for most container operations |
705 | * | |
706 | * Inputs: argv[0] - cnt_id | |
707 | * q - query name | |
708 | * cl - client name | |
709 | * | |
710 | * - check if that client is a member of the access control list | |
711 | * - OR, if the query is add_machine_to_container or delete_machine_from_container | |
712 | * check if the client is a memeber of the mem_acl list | |
713 | * - if the query is update_container and the container is to be renamed and | |
714 | * it is a top-level container, only priviledged users can do it | |
715 | */ | |
716 | ||
717 | int access_container(struct query *q, char *argv[], client *cl) | |
718 | { | |
719 | EXEC SQL BEGIN DECLARE SECTION; | |
73155abd | 720 | int cnt_id, acl_id, memacl_id, mach_id, machine_owner_id, flag; |
2fb668b0 | 721 | char acl_type[CONTAINERS_ACL_TYPE_SIZE], memacl_type[CONTAINERS_ACL_TYPE_SIZE]; |
722 | char name[CONTAINERS_NAME_SIZE], *newname; | |
73155abd | 723 | char machine_owner_type[MACHINE_OWNER_TYPE_SIZE]; |
2fb668b0 | 724 | EXEC SQL END DECLARE SECTION; |
725 | int status; | |
726 | ||
727 | cnt_id = *(int *)argv[0]; | |
728 | ||
729 | /* if amcn or dmcn, container id is the second argument */ | |
730 | if (strcmp(q->shortname, "amcn") == 0 || strcmp(q->shortname, "dmcn") == 0) | |
73155abd | 731 | { |
732 | mach_id = *(int *)argv[0]; | |
2fb668b0 | 733 | cnt_id = *(int *)argv[1]; |
73155abd | 734 | } |
2fb668b0 | 735 | |
73155abd | 736 | EXEC SQL SELECT acl_id, acl_type, memacl_id, memacl_type, name, publicflg |
737 | INTO :acl_id, :acl_type, :memacl_id, :memacl_type, :name, :flag | |
2fb668b0 | 738 | FROM containers |
739 | WHERE cnt_id = :cnt_id; | |
740 | ||
741 | if (sqlca.sqlerrd[2] != 1) | |
742 | return MR_INTERNAL; | |
743 | ||
744 | /* trim off the trailing spaces */ | |
745 | strcpy(name, strtrim(name)); | |
746 | ||
57d62784 | 747 | /* Only dbadmin can rename containers. */ |
2fb668b0 | 748 | if (!strcmp(q->shortname, "ucon")) |
749 | { | |
750 | newname = argv[1]; | |
57d62784 | 751 | if (strcmp(name, newname)) |
2fb668b0 | 752 | return MR_PERM; |
753 | } | |
754 | ||
755 | /* check for client in access control list and return success right | |
756 | * away if it's there. */ | |
757 | if (find_member(acl_type, acl_id, cl)) | |
758 | return MR_SUCCESS; | |
759 | ||
760 | /* If not amcn, dmcn, we lose. */ | |
761 | if (strcmp(q->shortname, "amcn") && strcmp(q->shortname, "dmcn")) | |
762 | return MR_PERM; | |
763 | ||
764 | if (find_member(memacl_type, memacl_id, cl)) | |
765 | return MR_SUCCESS; | |
766 | ||
73155abd | 767 | /* if the container is public or the query is delete, grant access if client |
768 | * is on owner list */ | |
769 | if (flag || q->type == DELETE) | |
770 | { | |
771 | EXEC SQL SELECT owner_type, owner_id INTO :machine_owner_type, | |
772 | :machine_owner_id | |
773 | FROM machine | |
774 | WHERE mach_id = :mach_id; | |
775 | ||
776 | if (sqlca.sqlerrd[2] == 1 && strcmp("NONE", machine_owner_type) && | |
777 | find_member(machine_owner_type, machine_owner_id, cl)) | |
778 | return MR_SUCCESS; | |
779 | } | |
2fb668b0 | 780 | /* Otherwise fail. */ |
781 | return MR_PERM; | |
782 | } |