]> andersk Git - moira.git/blame - server/qaccess.pc
add tag_member_of_list() function so we don't get broken incrementals
[moira.git] / server / qaccess.pc
CommitLineData
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 18EXEC SQL INCLUDE sqlca;
7ac48069 19
20RCSID("$Header$");
73cf66ba 21
22extern char *whoami;
03c05291 23extern int dbms_errno, mr_errcode;
73cf66ba 24
03c05291 25EXEC 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 36int 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
44
45
46/* access_login - verify that client name equals specified login name
47 *
48 * argv[0...n] contain search info. q->
49 */
50
5eaef520 51int access_login(struct query *q, char *argv[], client *cl)
73cf66ba 52{
5eaef520 53 EXEC SQL BEGIN DECLARE SECTION;
54 int id;
55 EXEC SQL END DECLARE SECTION;
73cf66ba 56
5eaef520 57 if (q->argc != 1)
58 return MR_ARGS;
03c05291 59
5eaef520 60 if (!strcmp(q->shortname, "gual"))
61 {
5906749e 62 EXEC SQL SELECT users_id INTO :id FROM users
cc0ec904 63 WHERE login = :argv[0] AND users_id != 0;
5eaef520 64 }
65 else if (!strcmp(q->shortname, "gubl"))
66 {
03c05291 67 EXEC SQL SELECT users_id INTO :id FROM users u
cc0ec904 68 WHERE u.login = :argv[0] AND u.users_id != 0;
5eaef520 69 }
70 else if (!strcmp(q->shortname, "guau"))
71 {
5906749e 72 EXEC SQL SELECT users_id INTO :id FROM users
73 WHERE unix_uid = :argv[0] AND users_id != 0;
5eaef520 74 }
75 else if (!strcmp(q->shortname, "gubu"))
76 {
03c05291 77 EXEC SQL SELECT users_id INTO :id FROM users u
78 WHERE u.unix_uid = :argv[0] AND u.users_id != 0;
73cf66ba 79 }
80
5eaef520 81 if (sqlca.sqlcode == SQL_NO_MATCH)
82 return MR_NO_MATCH; /* ought to be MR_USER, but this is what
83 gual returns, so we have to be consistent */
84 else if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
85 return MR_PERM;
86 else
87 return MR_SUCCESS;
73cf66ba 88}
89
90
f659afb2 91/* access_spob - check access for set_pobox */
92
93int access_spob(struct query *q, char *argv[], client *cl)
94{
51e578b6 95 EXEC SQL BEGIN DECLARE SECTION;
96 int id;
97 EXEC SQL END DECLARE SECTION;
98
99 if (!strcmp(argv[1], "IMAP"))
100 {
101 EXEC SQL SELECT owner INTO :id FROM filesys f
102 WHERE f.label = :argv[2] AND f.type = 'IMAP' AND
103 f.lockertype = 'USER';
104 if (cl->users_id != id)
105 return MR_PERM;
106 }
107 if (cl->users_id != *(int *)argv[0])
f659afb2 108 return MR_PERM;
109 else
110 return MR_SUCCESS;
111}
112
73cf66ba 113
114/* access_list - check access for most list operations
115 *
116 * Inputs: argv[0] - list_id
117 * q - query name
118 * argv[2] - member ID (only for queries "amtl" and "dmfl")
e688520a 119 * argv[7] - group ID (only for query "ulis")
73cf66ba 120 * cl - client name
121 *
122 * - check that client is a member of the access control list
123 * - OR, if the query is add_member_to_list or delete_member_from_list
124 * and the list is public, allow access if client = member
125 */
126
5eaef520 127int access_list(struct query *q, char *argv[], client *cl)
73cf66ba 128{
5eaef520 129 EXEC SQL BEGIN DECLARE SECTION;
130 int list_id, acl_id, flags, gid, users_id;
e688520a 131 char acl_type[LIST_ACL_TYPE_SIZE], name[LIST_NAME_SIZE], *newname;
5eaef520 132 EXEC SQL END DECLARE SECTION;
133 int status;
134
135 list_id = *(int *)argv[0];
17f090e1 136 EXEC SQL SELECT acl_id, acl_type, gid, publicflg, name
137 INTO :acl_id, :acl_type, :gid, :flags, :name
5eaef520 138 FROM list
139 WHERE list_id = :list_id;
140
141 if (sqlca.sqlerrd[2] != 1)
142 return MR_INTERNAL;
143
ae4cbe3d 144 /* Allow client to add self to public list or delete self from any
145 * list.
146 */
147 if ((((!strcmp("amtl", q->shortname) ||
148 !strcmp("atml", q->shortname)) && flags) ||
5eaef520 149 (!strcmp("dmfl", q->shortname))))
150 {
151 if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id)
152 return MR_SUCCESS;
153 if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id)
154 return MR_SUCCESS;
155 } /* if update_list, don't allow them to change the GID or rename to
156 a username other than their own */
157 else if (!strcmp("ulis", q->shortname))
158 {
159 if (!strcmp(argv[7], UNIQUE_GID))
160 {
161 if (gid != -1)
162 return MR_PERM;
163 }
164 else
165 {
166 if (gid != atoi(argv[7]))
167 return MR_PERM;
168 }
5c96d2cd 169
d83ee5a2 170 newname = argv[1];
5c96d2cd 171
172 if (!strcmp("ulis", q->shortname))
173 {
174 /* Check that it doesn't conflict with the Grouper namespace. */
175 if (strlen(newname) > 4 && isdigit(newname[2]) &&
176 isdigit(newname[3]) && newname[4] == '-')
177 {
178 if (!strncasecmp(newname, "fa", 2) ||
179 !strncasecmp(newname, "sp", 2) ||
180 !strncasecmp(newname, "su", 2) ||
181 !strncasecmp(newname, "ja", 2))
182 return MR_RESERVED;
183 }
184
185 /* Don't let anyone take owner-foo list names. They interact
186 * weirdly with the aliases automatically generated by
187 * mailhub.gen.
188 */
189 if (!strncasecmp(newname, "owner-", 6))
190 return MR_RESERVED;
191 }
192
d83ee5a2 193 EXEC SQL SELECT users_id INTO :users_id FROM users
5eaef520 194 WHERE login = :newname;
17f090e1 195 if ((sqlca.sqlcode != SQL_NO_MATCH) && strcmp(strtrim(name), newname) &&
196 (users_id != cl->users_id))
5eaef520 197 return MR_PERM;
73cf66ba 198 }
199
5eaef520 200 /* check for client in access control list */
201 status = find_member(acl_type, acl_id, cl);
202 if (!status)
203 return MR_PERM;
73cf66ba 204
5eaef520 205 return MR_SUCCESS;
73cf66ba 206}
207
208
209/* access_visible_list - allow access to list only if it is not hidden,
210 * or if the client is on the ACL
211 *
212 * Inputs: argv[0] - list_id
213 * cl - client identifier
214 */
215
5eaef520 216int access_visible_list(struct query *q, char *argv[], client *cl)
73cf66ba 217{
5eaef520 218 EXEC SQL BEGIN DECLARE SECTION;
219 int list_id, acl_id, flags ;
e688520a 220 char acl_type[LIST_ACL_TYPE_SIZE];
5eaef520 221 EXEC SQL END DECLARE SECTION;
222 int status;
223
224 list_id = *(int *)argv[0];
225 EXEC SQL SELECT hidden, acl_id, acl_type
226 INTO :flags, :acl_id, :acl_type
227 FROM list
228 WHERE list_id = :list_id;
229 if (sqlca.sqlerrd[2] != 1)
230 return MR_INTERNAL;
231 if (!flags)
232 return MR_SUCCESS;
233
234 /* check for client in access control list */
235 status = find_member(acl_type, acl_id, cl);
236 if (!status)
237 return MR_PERM;
238
239 return MR_SUCCESS;
73cf66ba 240}
241
242
243/* access_vis_list_by_name - allow access to list only if it is not hidden,
244 * or if the client is on the ACL
245 *
246 * Inputs: argv[0] - list name
247 * cl - client identifier
248 */
249
5eaef520 250int access_vis_list_by_name(struct query *q, char *argv[], client *cl)
73cf66ba 251{
5eaef520 252 EXEC SQL BEGIN DECLARE SECTION;
253 int acl_id, flags, rowcount;
e688520a 254 char acl_type[LIST_ACL_TYPE_SIZE], *listname;
5eaef520 255 EXEC SQL END DECLARE SECTION;
256 int status;
257
258 listname = argv[0];
259 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
260 FROM list WHERE name = :listname;
261
262 rowcount = sqlca.sqlerrd[2];
263 if (rowcount > 1)
264 return MR_WILDCARD;
265 if (rowcount == 0)
266 return MR_NO_MATCH;
267 if (!flags)
268 return MR_SUCCESS;
269
270 /* check for client in access control list */
271 status = find_member(acl_type, acl_id, cl);
272 if (!status)
273 return MR_PERM;
274
275 return MR_SUCCESS;
73cf66ba 276}
277
278
279/* access_member - allow user to access member of type "USER" and name matches
f3c08a60 280 * username, or to access member of type "KERBEROS" and the principal matches
281 * the user, or to access member of type "LIST" and list is one that user is
73cf66ba 282 * on the acl of, or the list is visible.
283 */
284
5eaef520 285int access_member(struct query *q, char *argv[], client *cl)
73cf66ba 286{
5eaef520 287 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
288 return access_visible_list(q, &argv[1], cl);
73cf66ba 289
5eaef520 290 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER"))
291 {
292 if (cl->users_id == *(int *)argv[1])
293 return MR_SUCCESS;
73cf66ba 294 }
295
5eaef520 296 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS"))
297 {
298 if (cl->client_id == -*(int *)argv[1])
299 return MR_SUCCESS;
73cf66ba 300 }
301
5eaef520 302 return MR_PERM;
73cf66ba 303}
304
305
306/* access_qgli - special access routine for Qualified_get_lists. Allows
307 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
308 */
309
5eaef520 310int access_qgli(struct query *q, char *argv[], client *cl)
73cf66ba 311{
5eaef520 312 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
313 return MR_SUCCESS;
314 return MR_PERM;
73cf66ba 315}
316
317
318/* access_service - allow access if user is on ACL of service. Don't
319 * allow access if a wildcard is used.
320 */
321
5eaef520 322int access_service(struct query *q, char *argv[], client *cl)
73cf66ba 323{
5eaef520 324 EXEC SQL BEGIN DECLARE SECTION;
325 int acl_id;
e688520a 326 char *name, acl_type[LIST_ACL_TYPE_SIZE];
5eaef520 327 EXEC SQL END DECLARE SECTION;
328 int status;
329 char *c;
330
331 name = argv[0];
332 for (c = name; *c; c++)
333 {
334 if (islower(*c))
335 *c = toupper(*c);
336 }
337 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
338 WHERE name = :name;
339 if (sqlca.sqlerrd[2] > 1)
340 return MR_PERM;
341
342 /* check for client in access control list */
343 status = find_member(acl_type, acl_id, cl);
344 if (!status)
345 return MR_PERM;
346
347 return MR_SUCCESS;
73cf66ba 348}
349
350
351/* access_filesys - verify that client is owner or on owners list of filesystem
352 * named by argv[0]
353 */
354
5eaef520 355int access_filesys(struct query *q, char *argv[], client *cl)
73cf66ba 356{
5eaef520 357 EXEC SQL BEGIN DECLARE SECTION;
358 int users_id, list_id;
359 char *name;
360 EXEC SQL END DECLARE SECTION;
361 int status;
362
363 name = argv[0];
364 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
365 WHERE label = :name;
366
367 if (sqlca.sqlerrd[2] != 1)
368 return MR_PERM;
369 if (users_id == cl->users_id)
370 return MR_SUCCESS;
371 status = find_member("LIST", list_id, cl);
372 if (status)
373 return MR_SUCCESS;
374 else
375 return MR_PERM;
73cf66ba 376}
377
1beb5e23 378
379/* access_host - successful if owner of host, or subnet containing host
380 */
381
5eaef520 382int access_host(struct query *q, char *argv[], client *cl)
1beb5e23 383{
5eaef520 384 EXEC SQL BEGIN DECLARE SECTION;
385 int mid, sid, id;
e688520a 386 char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
5eaef520 387 EXEC SQL END DECLARE SECTION;
388 int status;
389
17f090e1 390 if (q->type == RETRIEVE)
391 {
392 if (strcmp(argv[0], "*") || strcmp(argv[1], "*") ||
393 strcmp(argv[2], "*") || strcmp(argv[3], "*"))
394 return MR_SUCCESS;
395 else
396 return MR_PERM;
397 }
9e252e6f 398
5eaef520 399 if (q->type == APPEND)
400 {
17f090e1 401 /* Non-query owner must set use to zero */
402 if (atoi(argv[6]) != 0)
403 return MR_PERM;
404
9e252e6f 405 /* ... and start the hostname with a letter */
406 if (isdigit(argv[0][0]))
407 return MR_BAD_CHAR;
408
5eaef520 409 id = *(int *)argv[8];
410 EXEC SQL SELECT s.owner_type, s.owner_id
411 INTO :stype, :sid FROM subnet s
412 WHERE s.snet_id = :id;
413 mid = 0;
17f090e1 414
415 if (find_member(stype, sid, cl))
5eaef520 416 return MR_SUCCESS;
417 else
418 return MR_PERM;
419 }
17f090e1 420 else /* q-type == UPDATE */
5eaef520 421 {
17f090e1 422 EXEC SQL BEGIN DECLARE SECTION;
423 int status, acomment, use, ocomment, snid;
e688520a 424 char contact[MACHINE_CONTACT_SIZE], address[MACHINE_ADDRESS_SIZE];
9e252e6f 425 char name[MACHINE_NAME_SIZE];
17f090e1 426 EXEC SQL END DECLARE SECTION;
427
5eaef520 428 id = *(int *)argv[0];
9e252e6f 429 EXEC SQL SELECT m.name, m.use, m.contact, m.status, m.address,
430 m.owner_type, m.owner_id, m.acomment, m.ocomment, m.snet_id,
431 s.owner_type, s.owner_id INTO :name, :use, :contact, :status,
432 :address, :mtype, :mid, :acomment, :ocomment, :snid, :stype, :sid
17f090e1 433 FROM machine m, subnet s
434 WHERE m.mach_id = :id AND s.snet_id = m.snet_id;
435 if (dbms_errno)
436 return mr_errcode;
437
438 /* non-query-owner cannot change use or ocomment */
439 if ((use != atoi(argv[7])) || (ocomment != *(int *)argv[14]))
440 return MR_PERM;
441
9e252e6f 442 /* or rename to start with digit */
443 if (isdigit(argv[1][0]) && strcmp(strtrim(name), argv[1]))
444 return MR_BAD_CHAR;
445
17f090e1 446 if (!find_member(stype, sid, cl))
447 {
448 if (find_member(mtype, mid, cl))
449 {
450 /* host owner also cannot change contact, status, address,
451 owner, or acomment */
452 if (strcmp(argv[6], strtrim(contact)) ||
453 (status != atoi(argv[8])) ||
454 strcmp(argv[10], strtrim(address)) ||
455 strcmp(argv[11], strtrim(mtype)) ||
456 (mid != *(int *)argv[12]) || (acomment != *(int *)argv[13]))
457 return MR_PERM;
458 }
459 else
460 return MR_PERM;
461 }
462
463 /* If moving to a new subnet, make sure user is on acl there */
464 id = *(int *)argv[9];
465 if (id != snid)
466 {
467 EXEC SQL SELECT owner_type, owner_id INTO :stype, :sid
468 FROM subnet WHERE snet_id=:id;
469 if (!find_member(stype, sid, cl))
470 return MR_PERM;
471 }
5eaef520 472
5eaef520 473 return MR_SUCCESS;
1beb5e23 474 }
1beb5e23 475}
476
477
478/* access_ahal - check for adding a host alias.
479 * successful if host has less then 2 aliases and (client is owner of
480 * host or subnet).
481 * If deleting an alias, any owner will do.
482 */
483
5eaef520 484int access_ahal(struct query *q, char *argv[], client *cl)
1beb5e23 485{
5eaef520 486 EXEC SQL BEGIN DECLARE SECTION;
487 int cnt, id, mid, sid;
e688520a 488 char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
5eaef520 489 EXEC SQL END DECLARE SECTION;
490 int status;
491
492 if (q->type == RETRIEVE)
493 return MR_SUCCESS;
494
495 id = *(int *)argv[1];
496
9e252e6f 497 if (q->type == APPEND && isdigit(argv[0][0]))
498 return MR_BAD_CHAR;
499
5eaef520 500 EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
501 if (dbms_errno)
502 return mr_errcode;
503 /* if the type is APPEND, this is ahal and we need to make sure there
504 * will be no more than 2 aliases. If it's not, it must be dhal and
505 * any owner will do.
506 */
507 if (q->type == APPEND && cnt >= 2)
508 return MR_PERM;
509 EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
510 INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
511 WHERE m.mach_id = :id and s.snet_id = m.snet_id;
512 status = find_member(mtype, mid, cl);
513 if (status)
514 return MR_SUCCESS;
515 status = find_member(stype, sid, cl);
516 if (status)
517 return MR_SUCCESS;
518 else
519 return MR_PERM;
1beb5e23 520}
7cf83f0f 521
522
7cf83f0f 523/* access_snt - check for retrieving network structure
524 */
525
5eaef520 526int access_snt(struct query *q, char *argv[], client *cl)
7cf83f0f 527{
5eaef520 528 if (q->type == RETRIEVE)
529 return MR_SUCCESS;
7cf83f0f 530
5eaef520 531 return MR_PERM;
7cf83f0f 532}
1a9a0a59 533
534
535/* access_printer */
536int access_printer(struct query *q, char *argv[], client *cl)
537{
538 EXEC SQL BEGIN DECLARE SECTION;
539 char type[PRINTSERVERS_OWNER_TYPE_SIZE];
540 int id, mach_id;
541 EXEC SQL END DECLARE SECTION;
542 int status;
543
544 mach_id = *(int *)argv[PRN_RM];
545 EXEC SQL SELECT owner_type, owner_id INTO :type, :id
546 FROM printservers WHERE mach_id = :mach_id;
547 if (sqlca.sqlcode)
548 return MR_PERM;
549
550 status = find_member(type, id, cl);
551 if (status)
552 return MR_SUCCESS;
553 else
554 return MR_PERM;
555}
This page took 0.145165 seconds and 5 git commands to generate.