]> andersk Git - moira.git/blame - server/qaccess.pc
from epeisach: fallback to hes_getservbyname if we're not in /etc/services
[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{
95 if (cl->users_id != *(int *)argv[0] || !strcmp(argv[1], "IMAP"))
96 return MR_PERM;
97 else
98 return MR_SUCCESS;
99}
100
73cf66ba 101
102/* access_list - check access for most list operations
103 *
104 * Inputs: argv[0] - list_id
105 * q - query name
106 * argv[2] - member ID (only for queries "amtl" and "dmfl")
e688520a 107 * argv[7] - group ID (only for query "ulis")
73cf66ba 108 * cl - client name
109 *
110 * - check that client is a member of the access control list
111 * - OR, if the query is add_member_to_list or delete_member_from_list
112 * and the list is public, allow access if client = member
113 */
114
5eaef520 115int access_list(struct query *q, char *argv[], client *cl)
73cf66ba 116{
5eaef520 117 EXEC SQL BEGIN DECLARE SECTION;
118 int list_id, acl_id, flags, gid, users_id;
e688520a 119 char acl_type[LIST_ACL_TYPE_SIZE], name[LIST_NAME_SIZE], *newname;
5eaef520 120 EXEC SQL END DECLARE SECTION;
121 int status;
122
123 list_id = *(int *)argv[0];
17f090e1 124 EXEC SQL SELECT acl_id, acl_type, gid, publicflg, name
125 INTO :acl_id, :acl_type, :gid, :flags, :name
5eaef520 126 FROM list
127 WHERE list_id = :list_id;
128
129 if (sqlca.sqlerrd[2] != 1)
130 return MR_INTERNAL;
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 {
136 if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id)
137 return MR_SUCCESS;
138 if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id)
139 return MR_SUCCESS;
140 } /* if update_list, don't allow them to change the GID or rename to
141 a username other than their own */
142 else if (!strcmp("ulis", q->shortname))
143 {
144 if (!strcmp(argv[7], UNIQUE_GID))
145 {
146 if (gid != -1)
147 return MR_PERM;
148 }
149 else
150 {
151 if (gid != atoi(argv[7]))
152 return MR_PERM;
153 }
d83ee5a2 154 newname = argv[1];
155 EXEC SQL SELECT users_id INTO :users_id FROM users
5eaef520 156 WHERE login = :newname;
17f090e1 157 if ((sqlca.sqlcode != SQL_NO_MATCH) && strcmp(strtrim(name), newname) &&
158 (users_id != cl->users_id))
5eaef520 159 return MR_PERM;
73cf66ba 160 }
161
5eaef520 162 /* check for client in access control list */
163 status = find_member(acl_type, acl_id, cl);
164 if (!status)
165 return MR_PERM;
73cf66ba 166
5eaef520 167 return MR_SUCCESS;
73cf66ba 168}
169
170
171/* access_visible_list - allow access to list only if it is not hidden,
172 * or if the client is on the ACL
173 *
174 * Inputs: argv[0] - list_id
175 * cl - client identifier
176 */
177
5eaef520 178int access_visible_list(struct query *q, char *argv[], client *cl)
73cf66ba 179{
5eaef520 180 EXEC SQL BEGIN DECLARE SECTION;
181 int list_id, acl_id, flags ;
e688520a 182 char acl_type[LIST_ACL_TYPE_SIZE];
5eaef520 183 EXEC SQL END DECLARE SECTION;
184 int status;
185
186 list_id = *(int *)argv[0];
187 EXEC SQL SELECT hidden, acl_id, acl_type
188 INTO :flags, :acl_id, :acl_type
189 FROM list
190 WHERE list_id = :list_id;
191 if (sqlca.sqlerrd[2] != 1)
192 return MR_INTERNAL;
193 if (!flags)
194 return MR_SUCCESS;
195
196 /* check for client in access control list */
197 status = find_member(acl_type, acl_id, cl);
198 if (!status)
199 return MR_PERM;
200
201 return MR_SUCCESS;
73cf66ba 202}
203
204
205/* access_vis_list_by_name - allow access to list only if it is not hidden,
206 * or if the client is on the ACL
207 *
208 * Inputs: argv[0] - list name
209 * cl - client identifier
210 */
211
5eaef520 212int access_vis_list_by_name(struct query *q, char *argv[], client *cl)
73cf66ba 213{
5eaef520 214 EXEC SQL BEGIN DECLARE SECTION;
215 int acl_id, flags, rowcount;
e688520a 216 char acl_type[LIST_ACL_TYPE_SIZE], *listname;
5eaef520 217 EXEC SQL END DECLARE SECTION;
218 int status;
219
220 listname = argv[0];
221 EXEC SQL SELECT hidden, acl_id, acl_type INTO :flags, :acl_id, :acl_type
222 FROM list WHERE name = :listname;
223
224 rowcount = sqlca.sqlerrd[2];
225 if (rowcount > 1)
226 return MR_WILDCARD;
227 if (rowcount == 0)
228 return MR_NO_MATCH;
229 if (!flags)
230 return MR_SUCCESS;
231
232 /* check for client in access control list */
233 status = find_member(acl_type, acl_id, cl);
234 if (!status)
235 return MR_PERM;
236
237 return MR_SUCCESS;
73cf66ba 238}
239
240
241/* access_member - allow user to access member of type "USER" and name matches
f3c08a60 242 * username, or to access member of type "KERBEROS" and the principal matches
243 * the user, or to access member of type "LIST" and list is one that user is
73cf66ba 244 * on the acl of, or the list is visible.
245 */
246
5eaef520 247int access_member(struct query *q, char *argv[], client *cl)
73cf66ba 248{
5eaef520 249 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
250 return access_visible_list(q, &argv[1], cl);
73cf66ba 251
5eaef520 252 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER"))
253 {
254 if (cl->users_id == *(int *)argv[1])
255 return MR_SUCCESS;
73cf66ba 256 }
257
5eaef520 258 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS"))
259 {
260 if (cl->client_id == -*(int *)argv[1])
261 return MR_SUCCESS;
73cf66ba 262 }
263
5eaef520 264 return MR_PERM;
73cf66ba 265}
266
267
268/* access_qgli - special access routine for Qualified_get_lists. Allows
269 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
270 */
271
5eaef520 272int access_qgli(struct query *q, char *argv[], client *cl)
73cf66ba 273{
5eaef520 274 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
275 return MR_SUCCESS;
276 return MR_PERM;
73cf66ba 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
5eaef520 284int access_service(struct query *q, char *argv[], client *cl)
73cf66ba 285{
5eaef520 286 EXEC SQL BEGIN DECLARE SECTION;
287 int acl_id;
e688520a 288 char *name, acl_type[LIST_ACL_TYPE_SIZE];
5eaef520 289 EXEC SQL END DECLARE SECTION;
290 int status;
291 char *c;
292
293 name = argv[0];
294 for (c = name; *c; c++)
295 {
296 if (islower(*c))
297 *c = toupper(*c);
298 }
299 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
300 WHERE name = :name;
301 if (sqlca.sqlerrd[2] > 1)
302 return MR_PERM;
303
304 /* check for client in access control list */
305 status = find_member(acl_type, acl_id, cl);
306 if (!status)
307 return MR_PERM;
308
309 return MR_SUCCESS;
73cf66ba 310}
311
312
313/* access_filesys - verify that client is owner or on owners list of filesystem
314 * named by argv[0]
315 */
316
5eaef520 317int access_filesys(struct query *q, char *argv[], client *cl)
73cf66ba 318{
5eaef520 319 EXEC SQL BEGIN DECLARE SECTION;
320 int users_id, list_id;
321 char *name;
322 EXEC SQL END DECLARE SECTION;
323 int status;
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;
333 status = find_member("LIST", list_id, cl);
334 if (status)
335 return MR_SUCCESS;
336 else
337 return MR_PERM;
73cf66ba 338}
339
1beb5e23 340
341/* access_host - successful if owner of host, or subnet containing host
342 */
343
5eaef520 344int access_host(struct query *q, char *argv[], client *cl)
1beb5e23 345{
5eaef520 346 EXEC SQL BEGIN DECLARE SECTION;
347 int mid, sid, id;
e688520a 348 char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
5eaef520 349 EXEC SQL END DECLARE SECTION;
350 int status;
351
17f090e1 352 if (q->type == RETRIEVE)
353 {
354 if (strcmp(argv[0], "*") || strcmp(argv[1], "*") ||
355 strcmp(argv[2], "*") || strcmp(argv[3], "*"))
356 return MR_SUCCESS;
357 else
358 return MR_PERM;
359 }
9e252e6f 360
5eaef520 361 if (q->type == APPEND)
362 {
17f090e1 363 /* Non-query owner must set use to zero */
364 if (atoi(argv[6]) != 0)
365 return MR_PERM;
366
9e252e6f 367 /* ... and start the hostname with a letter */
368 if (isdigit(argv[0][0]))
369 return MR_BAD_CHAR;
370
5eaef520 371 id = *(int *)argv[8];
372 EXEC SQL SELECT s.owner_type, s.owner_id
373 INTO :stype, :sid FROM subnet s
374 WHERE s.snet_id = :id;
375 mid = 0;
17f090e1 376
377 if (find_member(stype, sid, cl))
5eaef520 378 return MR_SUCCESS;
379 else
380 return MR_PERM;
381 }
17f090e1 382 else /* q-type == UPDATE */
5eaef520 383 {
17f090e1 384 EXEC SQL BEGIN DECLARE SECTION;
385 int status, acomment, use, ocomment, snid;
e688520a 386 char contact[MACHINE_CONTACT_SIZE], address[MACHINE_ADDRESS_SIZE];
9e252e6f 387 char name[MACHINE_NAME_SIZE];
17f090e1 388 EXEC SQL END DECLARE SECTION;
389
5eaef520 390 id = *(int *)argv[0];
9e252e6f 391 EXEC SQL SELECT m.name, m.use, m.contact, m.status, m.address,
392 m.owner_type, m.owner_id, m.acomment, m.ocomment, m.snet_id,
393 s.owner_type, s.owner_id INTO :name, :use, :contact, :status,
394 :address, :mtype, :mid, :acomment, :ocomment, :snid, :stype, :sid
17f090e1 395 FROM machine m, subnet s
396 WHERE m.mach_id = :id AND s.snet_id = m.snet_id;
397 if (dbms_errno)
398 return mr_errcode;
399
400 /* non-query-owner cannot change use or ocomment */
401 if ((use != atoi(argv[7])) || (ocomment != *(int *)argv[14]))
402 return MR_PERM;
403
9e252e6f 404 /* or rename to start with digit */
405 if (isdigit(argv[1][0]) && strcmp(strtrim(name), argv[1]))
406 return MR_BAD_CHAR;
407
17f090e1 408 if (!find_member(stype, sid, cl))
409 {
410 if (find_member(mtype, mid, cl))
411 {
412 /* host owner also cannot change contact, status, address,
413 owner, or acomment */
414 if (strcmp(argv[6], strtrim(contact)) ||
415 (status != atoi(argv[8])) ||
416 strcmp(argv[10], strtrim(address)) ||
417 strcmp(argv[11], strtrim(mtype)) ||
418 (mid != *(int *)argv[12]) || (acomment != *(int *)argv[13]))
419 return MR_PERM;
420 }
421 else
422 return MR_PERM;
423 }
424
425 /* If moving to a new subnet, make sure user is on acl there */
426 id = *(int *)argv[9];
427 if (id != snid)
428 {
429 EXEC SQL SELECT owner_type, owner_id INTO :stype, :sid
430 FROM subnet WHERE snet_id=:id;
431 if (!find_member(stype, sid, cl))
432 return MR_PERM;
433 }
5eaef520 434
5eaef520 435 return MR_SUCCESS;
1beb5e23 436 }
1beb5e23 437}
438
439
440/* access_ahal - check for adding a host alias.
441 * successful if host has less then 2 aliases and (client is owner of
442 * host or subnet).
443 * If deleting an alias, any owner will do.
444 */
445
5eaef520 446int access_ahal(struct query *q, char *argv[], client *cl)
1beb5e23 447{
5eaef520 448 EXEC SQL BEGIN DECLARE SECTION;
449 int cnt, id, mid, sid;
e688520a 450 char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
5eaef520 451 EXEC SQL END DECLARE SECTION;
452 int status;
453
454 if (q->type == RETRIEVE)
455 return MR_SUCCESS;
456
457 id = *(int *)argv[1];
458
9e252e6f 459 if (q->type == APPEND && isdigit(argv[0][0]))
460 return MR_BAD_CHAR;
461
5eaef520 462 EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
463 if (dbms_errno)
464 return mr_errcode;
465 /* if the type is APPEND, this is ahal and we need to make sure there
466 * will be no more than 2 aliases. If it's not, it must be dhal and
467 * any owner will do.
468 */
469 if (q->type == APPEND && cnt >= 2)
470 return MR_PERM;
471 EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
472 INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
473 WHERE m.mach_id = :id and s.snet_id = m.snet_id;
474 status = find_member(mtype, mid, cl);
475 if (status)
476 return MR_SUCCESS;
477 status = find_member(stype, sid, cl);
478 if (status)
479 return MR_SUCCESS;
480 else
481 return MR_PERM;
1beb5e23 482}
7cf83f0f 483
484
7cf83f0f 485/* access_snt - check for retrieving network structure
486 */
487
5eaef520 488int access_snt(struct query *q, char *argv[], client *cl)
7cf83f0f 489{
5eaef520 490 if (q->type == RETRIEVE)
491 return MR_SUCCESS;
7cf83f0f 492
5eaef520 493 return MR_PERM;
7cf83f0f 494}
1a9a0a59 495
496
497/* access_printer */
498int access_printer(struct query *q, char *argv[], client *cl)
499{
500 EXEC SQL BEGIN DECLARE SECTION;
501 char type[PRINTSERVERS_OWNER_TYPE_SIZE];
502 int id, mach_id;
503 EXEC SQL END DECLARE SECTION;
504 int status;
505
506 mach_id = *(int *)argv[PRN_RM];
507 EXEC SQL SELECT owner_type, owner_id INTO :type, :id
508 FROM printservers WHERE mach_id = :mach_id;
509 if (sqlca.sqlcode)
510 return MR_PERM;
511
512 status = find_member(type, id, cl);
513 if (status)
514 return MR_SUCCESS;
515 else
516 return MR_PERM;
517}
This page took 0.246753 seconds and 5 git commands to generate.