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