]> andersk Git - moira.git/blame - server/qaccess.pc
Command line printer manipulation client, and build goo.
[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>
7b12515f 17#include <netdb.h>
b4b129dd 18#include <sys/types.h>
19#include <netinet/in.h>
20#include <arpa/nameser.h>
7ac48069 21
73cf66ba 22EXEC SQL INCLUDE sqlca;
7ac48069 23
24RCSID("$Header$");
73cf66ba 25
26extern char *whoami;
03c05291 27extern int dbms_errno, mr_errcode;
73cf66ba 28
03c05291 29EXEC SQL WHENEVER SQLERROR DO dbmserr();
73cf66ba 30
31
32/* Specialized Access Routines */
33
34/* access_user - verify that client name equals specified login name
35 *
36 * - since field validation routines are called first, a users_id is
37 * now in argv[0] instead of the login name.
38 */
39
5eaef520 40int access_user(struct query *q, char *argv[], client *cl)
73cf66ba 41{
5eaef520 42 if (cl->users_id != *(int *)argv[0])
43 return MR_PERM;
44 else
45 return MR_SUCCESS;
73cf66ba 46}
47
34b6375c 48int access_update_user(struct query *q, char *argv[], client *cl)
49{
50 EXEC SQL BEGIN DECLARE SECTION;
51 int users_id, unix_uid, status, comments, secure;
52 char login[USERS_LOGIN_SIZE], shell[USERS_SHELL_SIZE];
53 char winconsoleshell[USERS_WINCONSOLESHELL_SIZE], last[USERS_LAST_SIZE];
54 char first[USERS_FIRST_SIZE], middle[USERS_MIDDLE_SIZE];
55 char clearid[USERS_CLEARID_SIZE], type[USERS_TYPE_SIZE];
56 char signature[USERS_SIGNATURE_SIZE];
57 EXEC SQL END DECLARE SECTION;
73cf66ba 58
34b6375c 59 /* The two fields we let users update themselves didn't appear until
60 * version 11.
61 */
62 if (q->version < 11)
63 return MR_PERM;
64
65 if (cl->users_id != *(int *)argv[0])
66 return MR_PERM;
67
68 users_id = *(int *)argv[0];
69
70 EXEC SQL SELECT u.login, u.unix_uid, u.shell, u.winconsoleshell, u.last,
71 u.first, u.middle, u.status, u.clearid, u.type, u.comments, u.signature,
72 u.secure INTO :login, :unix_uid, :shell, :winconsoleshell, :last, :first,
73 :middle, :status, :clearid, :type, :comments, :signature, :secure
74 FROM USERS u WHERE u.users_id = :users_id;
75
76 /* None of these things can have changed. */
77 if (strcmp(argv[1], strtrim(login)) ||
78 (unix_uid != atoi(argv[2])) ||
79 strcmp(argv[3], strtrim(shell)) ||
80 strcmp(argv[4], strtrim(winconsoleshell)) ||
81 strcmp(argv[5], strtrim(last)) ||
82 strcmp(argv[6], strtrim(first)) ||
83 strcmp(argv[7], strtrim(middle)) ||
84 (status != atoi(argv[8])) ||
85 strcmp(argv[9], strtrim(clearid)) ||
86 strcmp(argv[10], strtrim(type)) ||
87 (comments != *(int *)argv[11]) ||
88 strcmp(argv[12], strtrim(signature)) ||
89 (secure != atoi(argv[13])))
90 return MR_PERM;
91
92 return MR_SUCCESS;
93}
73cf66ba 94
95/* access_login - verify that client name equals specified login name
96 *
97 * argv[0...n] contain search info. q->
98 */
99
5eaef520 100int access_login(struct query *q, char *argv[], client *cl)
73cf66ba 101{
5eaef520 102 EXEC SQL BEGIN DECLARE SECTION;
103 int id;
104 EXEC SQL END DECLARE SECTION;
73cf66ba 105
5eaef520 106 if (q->argc != 1)
107 return MR_ARGS;
03c05291 108
5eaef520 109 if (!strcmp(q->shortname, "gual"))
110 {
5906749e 111 EXEC SQL SELECT users_id INTO :id FROM users
cc0ec904 112 WHERE login = :argv[0] AND users_id != 0;
5eaef520 113 }
114 else if (!strcmp(q->shortname, "gubl"))
115 {
03c05291 116 EXEC SQL SELECT users_id INTO :id FROM users u
cc0ec904 117 WHERE u.login = :argv[0] AND u.users_id != 0;
5eaef520 118 }
119 else if (!strcmp(q->shortname, "guau"))
120 {
5906749e 121 EXEC SQL SELECT users_id INTO :id FROM users
122 WHERE unix_uid = :argv[0] AND users_id != 0;
5eaef520 123 }
124 else if (!strcmp(q->shortname, "gubu"))
125 {
03c05291 126 EXEC SQL SELECT users_id INTO :id FROM users u
127 WHERE u.unix_uid = :argv[0] AND u.users_id != 0;
73cf66ba 128 }
129
5eaef520 130 if (sqlca.sqlcode == SQL_NO_MATCH)
131 return MR_NO_MATCH; /* ought to be MR_USER, but this is what
132 gual returns, so we have to be consistent */
133 else if (sqlca.sqlerrd[2] != 1 || id != cl->users_id)
134 return MR_PERM;
135 else
136 return MR_SUCCESS;
73cf66ba 137}
138
139
f659afb2 140/* access_spob - check access for set_pobox */
141
142int access_spob(struct query *q, char *argv[], client *cl)
143{
51e578b6 144 EXEC SQL BEGIN DECLARE SECTION;
145 int id;
146 EXEC SQL END DECLARE SECTION;
7b12515f 147 int status;
51e578b6 148
149 if (!strcmp(argv[1], "IMAP"))
22bbb6f0 150 {
151 EXEC SQL SELECT owner INTO :id FROM filesys f
152 WHERE f.label = :argv[2] AND f.type = 'IMAP' AND
153 f.lockertype = 'USER';
154 if (cl->users_id != id)
155 return MR_PERM;
156 }
7b12515f 157
158 /* Non-query owners can't forward mail to a POSTOFFICE or MAILHUB server,
159 * nor to a nonresolving domain.
160 */
161 if (!strcmp(argv[1], "SMTP") || !strcmp(argv[1], "SPLIT"))
162 {
163 status = check_mail_string(argv[2]);
164 if (status)
165 return status;
166 }
22bbb6f0 167
51e578b6 168 if (cl->users_id != *(int *)argv[0])
f659afb2 169 return MR_PERM;
170 else
171 return MR_SUCCESS;
172}
173
73cf66ba 174
175/* access_list - check access for most list operations
176 *
177 * Inputs: argv[0] - list_id
178 * q - query name
179 * argv[2] - member ID (only for queries "amtl" and "dmfl")
e688520a 180 * argv[7] - group ID (only for query "ulis")
73cf66ba 181 * cl - client name
182 *
183 * - check that client is a member of the access control list
184 * - OR, if the query is add_member_to_list or delete_member_from_list
185 * and the list is public, allow access if client = member
186 */
187
5eaef520 188int access_list(struct query *q, char *argv[], client *cl)
73cf66ba 189{
5eaef520 190 EXEC SQL BEGIN DECLARE SECTION;
40b33762 191 int list_id, acl_id, flags, gid, users_id, member_id, member_acl_id;
8e3761a2 192 int memacl_id, mailman, mailman_id;
e688520a 193 char acl_type[LIST_ACL_TYPE_SIZE], name[LIST_NAME_SIZE], *newname;
59c3208b 194 char member_acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE];
5eaef520 195 EXEC SQL END DECLARE SECTION;
8e3761a2 196 int status, cnt;
7b12515f 197 char *buf;
5eaef520 198
199 list_id = *(int *)argv[0];
40b33762 200 member_id = *(int *)argv[2];
59c3208b 201 EXEC SQL SELECT acl_id, acl_type, memacl_id, memacl_type,
8e3761a2 202 gid, publicflg, name, mailman, mailman_id
59c3208b 203 INTO :acl_id, :acl_type, :memacl_id, :memacl_type,
8e3761a2 204 :gid, :flags, :name, :mailman, :mailman_id
5eaef520 205 FROM list
206 WHERE list_id = :list_id;
207
208 if (sqlca.sqlerrd[2] != 1)
209 return MR_INTERNAL;
210
59c3208b 211 /* if update_list, don't allow them to change the GID or rename to a
212 username other than their own */
213 if (!strcmp("ulis", q->shortname))
5eaef520 214 {
215 if (!strcmp(argv[7], UNIQUE_GID))
216 {
217 if (gid != -1)
218 return MR_PERM;
219 }
220 else
221 {
222 if (gid != atoi(argv[7]))
223 return MR_PERM;
224 }
5c96d2cd 225
d83ee5a2 226 newname = argv[1];
5c96d2cd 227
8e3761a2 228 /* Check that it doesn't conflict with the Grouper namespace. */
229 if (strlen(newname) > 4 && isdigit(newname[2]) &&
230 isdigit(newname[3]) && newname[4] == '-')
231 {
232 if (!strncasecmp(newname, "fa", 2) ||
233 !strncasecmp(newname, "sp", 2) ||
234 !strncasecmp(newname, "su", 2) ||
235 !strncasecmp(newname, "ja", 2))
236 return MR_RESERVED;
237 }
238
239 /* Don't let anyone take owner-foo list names. They interact
240 * weirdly with the aliases automatically generated by
241 * mailhub.gen.
242 */
243 if (!strncasecmp(newname, "owner-", 6))
244 return MR_RESERVED;
245
d83ee5a2 246 EXEC SQL SELECT users_id INTO :users_id FROM users
5eaef520 247 WHERE login = :newname;
17f090e1 248 if ((sqlca.sqlcode != SQL_NO_MATCH) && strcmp(strtrim(name), newname) &&
249 (users_id != cl->users_id))
5eaef520 250 return MR_PERM;
8e3761a2 251
252 /* For modern enough clients, don't allow ordinary users to toggle
253 * the mailman bit or change the server.
254 */
255 if (q->version >= 10)
256 {
257 if (mailman != atoi(argv[9]))
258 return MR_PERM;
259
260 if (mailman_id != *(int *)argv[10])
261 return MR_PERM;
262 }
73cf66ba 263 }
264
7b12515f 265 /* Don't allow non-query owners to add STRINGs to lists if they end
266 * in a domain that's MIT.EDU or one of the hosts that provide the
267 * MAILHUB or POSTOFFICE services.
268 */
269 if (!strcmp(q->shortname, "amtl") || !strcmp(q->shortname, "atml"))
270 {
271 if (!strcmp("STRING", argv[1]))
272 {
273 buf = malloc(0);
274 status = id_to_name(*(int *)argv[2], STRINGS_TABLE, &buf);
275 if (status)
276 return status;
277
278 status = check_mail_string(buf);
279 free(buf);
280 if (status)
281 return status;
282 }
283 }
284
59c3208b 285 /* check for client in access control list and return success right
286 * away if it's there. */
287 if (find_member(acl_type, acl_id, cl))
288 return MR_SUCCESS;
289
290 /* If not amtl, atml, or dmfl, we lose. */
291 if (strcmp(q->shortname, "amtl") && strcmp(q->shortname, "atml") &&
e3fbe284 292 strcmp(q->shortname, "dmfl") && strcmp(q->shortname, "tmol"))
5eaef520 293 return MR_PERM;
73cf66ba 294
59c3208b 295 if (find_member(memacl_type, memacl_id, cl))
296 return MR_SUCCESS;
297
b9f9ab1c 298 if (flags || q->type == MR_Q_DELETE)
59c3208b 299 {
300 if (!strcmp("USER", argv[1]) && *(int *)argv[2] == cl->users_id)
301 return MR_SUCCESS;
302 if (!strcmp("KERBEROS", argv[1]) && *(int *)argv[2] == -cl->client_id)
303 return MR_SUCCESS;
304 if (!strcmp("LIST", argv[1]) && !strcmp("dmfl", q->shortname))
305 {
306 EXEC SQL SELECT acl_id, acl_type INTO :member_acl_id,
307 :member_acl_type
308 FROM list
309 WHERE list_id = :member_id;
310
311 if (find_member(member_acl_type, member_acl_id, cl))
312 return MR_SUCCESS;
313 }
314 }
315
316 /* Otherwise fail. */
317 return MR_PERM;
73cf66ba 318}
319
320
321/* access_visible_list - 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_id
325 * cl - client identifier
326 */
327
5eaef520 328int access_visible_list(struct query *q, char *argv[], client *cl)
73cf66ba 329{
5eaef520 330 EXEC SQL BEGIN DECLARE SECTION;
59c3208b 331 int list_id, acl_id, memacl_id, flags ;
332 char acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE];
5eaef520 333 EXEC SQL END DECLARE SECTION;
334 int status;
335
336 list_id = *(int *)argv[0];
59c3208b 337 EXEC SQL SELECT hidden, acl_id, acl_type, memacl_id, memacl_type
338 INTO :flags, :acl_id, :acl_type, :memacl_id, :memacl_type
5eaef520 339 FROM list
340 WHERE list_id = :list_id;
341 if (sqlca.sqlerrd[2] != 1)
342 return MR_INTERNAL;
343 if (!flags)
344 return MR_SUCCESS;
345
346 /* check for client in access control list */
347 status = find_member(acl_type, acl_id, cl);
348 if (!status)
59c3208b 349 {
350 status = find_member(memacl_type, memacl_id, cl);
351 if (!status)
352 return MR_PERM;
353 }
5eaef520 354 return MR_SUCCESS;
73cf66ba 355}
356
357
358/* access_vis_list_by_name - allow access to list only if it is not hidden,
359 * or if the client is on the ACL
360 *
361 * Inputs: argv[0] - list name
362 * cl - client identifier
363 */
364
5eaef520 365int access_vis_list_by_name(struct query *q, char *argv[], client *cl)
73cf66ba 366{
5eaef520 367 EXEC SQL BEGIN DECLARE SECTION;
2affa9d4 368 int acl_id, memacl_id, flags, rowcount, list_id;
59c3208b 369 char acl_type[LIST_ACL_TYPE_SIZE], memacl_type[LIST_ACL_TYPE_SIZE];
370 char *listname;
5eaef520 371 EXEC SQL END DECLARE SECTION;
372 int status;
373
374 listname = argv[0];
2affa9d4 375 EXEC SQL SELECT hidden, acl_id, acl_type, memacl_id, memacl_type, list_id
376 INTO :flags, :acl_id, :acl_type, :memacl_id, :memacl_type, :list_id
59c3208b 377 FROM list
378 WHERE name = :listname;
5eaef520 379
380 rowcount = sqlca.sqlerrd[2];
381 if (rowcount > 1)
382 return MR_WILDCARD;
383 if (rowcount == 0)
384 return MR_NO_MATCH;
385 if (!flags)
386 return MR_SUCCESS;
387
2affa9d4 388 /* If the user is a member of the acl, memacl, or the list itself,
389 * accept them.
390 */
5eaef520 391 status = find_member(acl_type, acl_id, cl);
392 if (!status)
2affa9d4 393 status = find_member(memacl_type, memacl_id, cl);
394 if (!status)
395 status = find_member("LIST", list_id, cl);
396 if (!status)
397 return MR_PERM;
398
5eaef520 399 return MR_SUCCESS;
73cf66ba 400}
401
402
403/* access_member - allow user to access member of type "USER" and name matches
f3c08a60 404 * username, or to access member of type "KERBEROS" and the principal matches
405 * the user, or to access member of type "LIST" and list is one that user is
d1d964a0 406 * on the acl of, or the list is visible. Allow anyone to look up list
407 * memberships of MACHINEs.
73cf66ba 408 */
409
5eaef520 410int access_member(struct query *q, char *argv[], client *cl)
73cf66ba 411{
5eaef520 412 if (!strcmp(argv[0], "LIST") || !strcmp(argv[0], "RLIST"))
413 return access_visible_list(q, &argv[1], cl);
73cf66ba 414
5eaef520 415 if (!strcmp(argv[0], "USER") || !strcmp(argv[0], "RUSER"))
416 {
417 if (cl->users_id == *(int *)argv[1])
418 return MR_SUCCESS;
73cf66ba 419 }
420
5eaef520 421 if (!strcmp(argv[0], "KERBEROS") || !strcmp(argv[0], "RKERBEROS"))
422 {
423 if (cl->client_id == -*(int *)argv[1])
424 return MR_SUCCESS;
73cf66ba 425 }
426
d1d964a0 427 if (!strcmp(argv[0], "MACHINE") || !strcmp(argv[0], "RMACHINE"))
428 return MR_SUCCESS;
429
5eaef520 430 return MR_PERM;
73cf66ba 431}
432
433
434/* access_qgli - special access routine for Qualified_get_lists. Allows
435 * access iff argv[0] == "TRUE" and argv[2] == "FALSE".
436 */
437
5eaef520 438int access_qgli(struct query *q, char *argv[], client *cl)
73cf66ba 439{
5eaef520 440 if (!strcmp(argv[0], "TRUE") && !strcmp(argv[2], "FALSE"))
441 return MR_SUCCESS;
442 return MR_PERM;
73cf66ba 443}
444
445
446/* access_service - allow access if user is on ACL of service. Don't
447 * allow access if a wildcard is used.
448 */
449
5eaef520 450int access_service(struct query *q, char *argv[], client *cl)
73cf66ba 451{
5eaef520 452 EXEC SQL BEGIN DECLARE SECTION;
453 int acl_id;
e688520a 454 char *name, acl_type[LIST_ACL_TYPE_SIZE];
5eaef520 455 EXEC SQL END DECLARE SECTION;
456 int status;
457 char *c;
458
459 name = argv[0];
460 for (c = name; *c; c++)
461 {
462 if (islower(*c))
463 *c = toupper(*c);
464 }
465 EXEC SQL SELECT acl_id, acl_type INTO :acl_id, :acl_type FROM servers
466 WHERE name = :name;
467 if (sqlca.sqlerrd[2] > 1)
468 return MR_PERM;
469
470 /* check for client in access control list */
471 status = find_member(acl_type, acl_id, cl);
472 if (!status)
473 return MR_PERM;
474
475 return MR_SUCCESS;
73cf66ba 476}
477
478
479/* access_filesys - verify that client is owner or on owners list of filesystem
480 * named by argv[0]
481 */
482
5eaef520 483int access_filesys(struct query *q, char *argv[], client *cl)
73cf66ba 484{
5eaef520 485 EXEC SQL BEGIN DECLARE SECTION;
486 int users_id, list_id;
487 char *name;
488 EXEC SQL END DECLARE SECTION;
489 int status;
490
491 name = argv[0];
492 EXEC SQL SELECT owner, owners INTO :users_id, :list_id FROM filesys
493 WHERE label = :name;
494
495 if (sqlca.sqlerrd[2] != 1)
496 return MR_PERM;
497 if (users_id == cl->users_id)
498 return MR_SUCCESS;
499 status = find_member("LIST", list_id, cl);
500 if (status)
501 return MR_SUCCESS;
502 else
503 return MR_PERM;
73cf66ba 504}
505
1beb5e23 506
507/* access_host - successful if owner of host, or subnet containing host
508 */
509
5eaef520 510int access_host(struct query *q, char *argv[], client *cl)
1beb5e23 511{
5eaef520 512 EXEC SQL BEGIN DECLARE SECTION;
4f6b1a05 513 int mid, sid, id, subnet_status;
e688520a 514 char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
4f6b1a05 515 char *account_number;
5eaef520 516 EXEC SQL END DECLARE SECTION;
e4ae0190 517 int status, idx;
518
519 if (q->version < 6)
520 idx = 0;
4f6b1a05 521 else if (q->version >= 6 && q->version < 8)
e4ae0190 522 idx = 1;
4f6b1a05 523 else
524 idx = 2;
525
b9f9ab1c 526 if (q->type == MR_Q_APPEND)
5eaef520 527 {
17f090e1 528 /* Non-query owner must set use to zero */
e4ae0190 529 if (atoi(argv[6 + idx]) != 0)
17f090e1 530 return MR_PERM;
531
9e252e6f 532 /* ... and start the hostname with a letter */
533 if (isdigit(argv[0][0]))
534 return MR_BAD_CHAR;
535
e4ae0190 536 id = *(int *)argv[8 + idx];
4f6b1a05 537 EXEC SQL SELECT s.owner_type, s.owner_id, s.status
538 INTO :stype, :sid, :subnet_status FROM subnet s
5eaef520 539 WHERE s.snet_id = :id;
540 mid = 0;
17f090e1 541
4f6b1a05 542 /* Non query owner must provide valid billing information. */
543 if (q->version >= 8)
544 {
545 if (subnet_status == SNET_STATUS_BILLABLE)
546 {
547 account_number = argv[7];
548 EXEC SQL SELECT account_number FROM accountnumbers
549 WHERE account_number = :account_number;
550 if (sqlca.sqlcode == SQL_NO_MATCH)
551 return MR_ACCOUNT_NUMBER;
552 }
553 }
554
17f090e1 555 if (find_member(stype, sid, cl))
5eaef520 556 return MR_SUCCESS;
557 else
558 return MR_PERM;
559 }
b9f9ab1c 560 else /* q-type == MR_Q_UPDATE */
5eaef520 561 {
17f090e1 562 EXEC SQL BEGIN DECLARE SECTION;
563 int status, acomment, use, ocomment, snid;
e688520a 564 char contact[MACHINE_CONTACT_SIZE], address[MACHINE_ADDRESS_SIZE];
9e252e6f 565 char name[MACHINE_NAME_SIZE];
e4ae0190 566 char billing_contact[MACHINE_BILLING_CONTACT_SIZE];
17f090e1 567 EXEC SQL END DECLARE SECTION;
568
5eaef520 569 id = *(int *)argv[0];
e4ae0190 570 EXEC SQL SELECT m.name, m.use, m.contact, m.billing_contact, m.status,
571 m.address, m.owner_type, m.owner_id, m.acomment, m.ocomment, m.snet_id,
4f6b1a05 572 s.owner_type, s.owner_id, s.status INTO :name, :use, :contact,
573 :billing_contact, :status, :address, :mtype, :mid, :acomment,
574 :ocomment, :snid, :stype, :sid, :subnet_status
17f090e1 575 FROM machine m, subnet s
576 WHERE m.mach_id = :id AND s.snet_id = m.snet_id;
577 if (dbms_errno)
578 return mr_errcode;
579
4f6b1a05 580 /* Non query owner must provide valid billing information. */
581 if (q->version >= 8)
582 {
c862fa4e 583 if ((subnet_status == SNET_STATUS_BILLABLE) &&
584 (atoi(argv[10]) != 3))
4f6b1a05 585 {
586 account_number = argv[8];
587 EXEC SQL SELECT account_number FROM accountnumbers
588 WHERE account_number = :account_number;
589 if (sqlca.sqlcode == SQL_NO_MATCH)
590 return MR_ACCOUNT_NUMBER;
591 }
592 }
593
17f090e1 594 /* non-query-owner cannot change use or ocomment */
e4ae0190 595 if ((use != atoi(argv[7 + idx])) || (ocomment != *(int *)argv[14 + idx]))
17f090e1 596 return MR_PERM;
597
9e252e6f 598 /* or rename to start with digit */
599 if (isdigit(argv[1][0]) && strcmp(strtrim(name), argv[1]))
600 return MR_BAD_CHAR;
601
17f090e1 602 if (!find_member(stype, sid, cl))
603 {
604 if (find_member(mtype, mid, cl))
605 {
606 /* host owner also cannot change contact, status, address,
607 owner, or acomment */
7617c632 608 if (strcmp(argv[6], strtrim(contact)) ||
e4ae0190 609 (status != atoi(argv[8 + idx])) ||
610 strcmp(argv[10 + idx], strtrim(address)) ||
611 strcmp(argv[11 + idx], strtrim(mtype)) ||
612 (mid != *(int *)argv[12 + idx]) ||
613 (acomment != *(int *)argv[13 + idx]))
17f090e1 614 return MR_PERM;
e4ae0190 615 /* Billing contact field didn't appear until version 6 */
616 if (q->version >= 6)
7617c632 617 if (strcmp(argv[7], strtrim(billing_contact)))
e4ae0190 618 return MR_PERM;
17f090e1 619 }
620 else
621 return MR_PERM;
622 }
623
624 /* If moving to a new subnet, make sure user is on acl there */
e4ae0190 625 id = *(int *)argv[9 + idx];
17f090e1 626 if (id != snid)
627 {
628 EXEC SQL SELECT owner_type, owner_id INTO :stype, :sid
629 FROM subnet WHERE snet_id=:id;
630 if (!find_member(stype, sid, cl))
631 return MR_PERM;
632 }
5eaef520 633
5eaef520 634 return MR_SUCCESS;
1beb5e23 635 }
1beb5e23 636}
637
638
639/* access_ahal - check for adding a host alias.
640 * successful if host has less then 2 aliases and (client is owner of
641 * host or subnet).
642 * If deleting an alias, any owner will do.
643 */
644
5eaef520 645int access_ahal(struct query *q, char *argv[], client *cl)
1beb5e23 646{
5eaef520 647 EXEC SQL BEGIN DECLARE SECTION;
648 int cnt, id, mid, sid;
e688520a 649 char mtype[MACHINE_OWNER_TYPE_SIZE], stype[SUBNET_OWNER_TYPE_SIZE];
5eaef520 650 EXEC SQL END DECLARE SECTION;
651 int status;
652
b9f9ab1c 653 if (q->type == MR_Q_RETRIEVE)
5eaef520 654 return MR_SUCCESS;
655
656 id = *(int *)argv[1];
657
b9f9ab1c 658 if (q->type == MR_Q_APPEND && isdigit(argv[0][0]))
9e252e6f 659 return MR_BAD_CHAR;
660
5eaef520 661 EXEC SQL SELECT count(name) INTO :cnt from hostalias WHERE mach_id = :id;
662 if (dbms_errno)
663 return mr_errcode;
b9f9ab1c 664 /* if the type is MR_Q_APPEND, this is ahal and we need to make sure there
5eaef520 665 * will be no more than 2 aliases. If it's not, it must be dhal and
666 * any owner will do.
667 */
b9f9ab1c 668 if (q->type == MR_Q_APPEND && cnt >= 2)
5eaef520 669 return MR_PERM;
670 EXEC SQL SELECT m.owner_type, m.owner_id, s.owner_type, s.owner_id
671 INTO :mtype, :mid, :stype, :sid FROM machine m, subnet s
672 WHERE m.mach_id = :id and s.snet_id = m.snet_id;
673 status = find_member(mtype, mid, cl);
674 if (status)
675 return MR_SUCCESS;
676 status = find_member(stype, sid, cl);
677 if (status)
678 return MR_SUCCESS;
679 else
680 return MR_PERM;
1beb5e23 681}
7cf83f0f 682
683
7cf83f0f 684/* access_snt - check for retrieving network structure
685 */
686
5eaef520 687int access_snt(struct query *q, char *argv[], client *cl)
7cf83f0f 688{
b9f9ab1c 689 if (q->type == MR_Q_RETRIEVE)
5eaef520 690 return MR_SUCCESS;
7cf83f0f 691
5eaef520 692 return MR_PERM;
7cf83f0f 693}
1a9a0a59 694
695
696/* access_printer */
697int access_printer(struct query *q, char *argv[], client *cl)
698{
699 EXEC SQL BEGIN DECLARE SECTION;
700 char type[PRINTSERVERS_OWNER_TYPE_SIZE];
701 int id, mach_id;
702 EXEC SQL END DECLARE SECTION;
703 int status;
704
705 mach_id = *(int *)argv[PRN_RM];
706 EXEC SQL SELECT owner_type, owner_id INTO :type, :id
707 FROM printservers WHERE mach_id = :mach_id;
708 if (sqlca.sqlcode)
709 return MR_PERM;
710
711 status = find_member(type, id, cl);
712 if (status)
713 return MR_SUCCESS;
714 else
715 return MR_PERM;
716}
d7ddc011 717
718/* access_zephyr */
719int access_zephyr(struct query *q, char *argv[], client *cl)
720{
721 EXEC SQL BEGIN DECLARE SECTION;
722 char type[ZEPHYR_OWNER_TYPE_SIZE];
723 char *class;
724 int id;
725 EXEC SQL END DECLARE SECTION;
726 int status;
727
728 class = argv[ZA_CLASS];
729 EXEC SQL SELECT owner_type, owner_id INTO :type, :id
730 FROM zephyr WHERE class = :class;
731 if (sqlca.sqlcode)
732 return MR_PERM;
733
734 status = find_member(type, id, cl);
735 if (status)
736 return MR_SUCCESS;
737 else
738 return MR_PERM;
739}
740
2fb668b0 741/* access_container - check access for most container operations
742 *
743 * Inputs: argv[0] - cnt_id
744 * q - query name
745 * cl - client name
746 *
747 * - check if that client is a member of the access control list
748 * - OR, if the query is add_machine_to_container or delete_machine_from_container
749 * check if the client is a memeber of the mem_acl list
750 * - if the query is update_container and the container is to be renamed and
751 * it is a top-level container, only priviledged users can do it
752 */
753
754int access_container(struct query *q, char *argv[], client *cl)
755{
756 EXEC SQL BEGIN DECLARE SECTION;
73155abd 757 int cnt_id, acl_id, memacl_id, mach_id, machine_owner_id, flag;
2fb668b0 758 char acl_type[CONTAINERS_ACL_TYPE_SIZE], memacl_type[CONTAINERS_ACL_TYPE_SIZE];
759 char name[CONTAINERS_NAME_SIZE], *newname;
73155abd 760 char machine_owner_type[MACHINE_OWNER_TYPE_SIZE];
2fb668b0 761 EXEC SQL END DECLARE SECTION;
762 int status;
763
764 cnt_id = *(int *)argv[0];
765
766 /* if amcn or dmcn, container id is the second argument */
767 if (strcmp(q->shortname, "amcn") == 0 || strcmp(q->shortname, "dmcn") == 0)
73155abd 768 {
769 mach_id = *(int *)argv[0];
2fb668b0 770 cnt_id = *(int *)argv[1];
73155abd 771 }
2fb668b0 772
73155abd 773 EXEC SQL SELECT acl_id, acl_type, memacl_id, memacl_type, name, publicflg
774 INTO :acl_id, :acl_type, :memacl_id, :memacl_type, :name, :flag
2fb668b0 775 FROM containers
776 WHERE cnt_id = :cnt_id;
777
778 if (sqlca.sqlerrd[2] != 1)
779 return MR_INTERNAL;
780
781 /* trim off the trailing spaces */
782 strcpy(name, strtrim(name));
783
57d62784 784 /* Only dbadmin can rename containers. */
2fb668b0 785 if (!strcmp(q->shortname, "ucon"))
786 {
787 newname = argv[1];
57d62784 788 if (strcmp(name, newname))
2fb668b0 789 return MR_PERM;
790 }
791
792 /* check for client in access control list and return success right
793 * away if it's there. */
794 if (find_member(acl_type, acl_id, cl))
795 return MR_SUCCESS;
796
797 /* If not amcn, dmcn, we lose. */
798 if (strcmp(q->shortname, "amcn") && strcmp(q->shortname, "dmcn"))
799 return MR_PERM;
800
801 if (find_member(memacl_type, memacl_id, cl))
802 return MR_SUCCESS;
803
73155abd 804 /* if the container is public or the query is delete, grant access if client
805 * is on owner list */
b9f9ab1c 806 if (flag || q->type == MR_Q_DELETE)
73155abd 807 {
808 EXEC SQL SELECT owner_type, owner_id INTO :machine_owner_type,
809 :machine_owner_id
810 FROM machine
811 WHERE mach_id = :mach_id;
812
813 if (sqlca.sqlerrd[2] == 1 && strcmp("NONE", machine_owner_type) &&
814 find_member(machine_owner_type, machine_owner_id, cl))
815 return MR_SUCCESS;
816 }
2fb668b0 817 /* Otherwise fail. */
818 return MR_PERM;
819}
7b12515f 820
821int check_mail_string(char *mailstring)
822{
823 EXEC SQL BEGIN DECLARE SECTION;
824 char mname[MACHINE_NAME_SIZE];
825 EXEC SQL END DECLARE SECTION;
826 char *p, *host, *hostdomain;
827 struct hostent *hp;
b4b129dd 828 struct mxentry *mxrecords = NULL;
7b12515f 829 int index;
830
831 p = strchr(mailstring, '@');
832 if (p)
833 {
834 host = strdup(++p);
835
836 /* Replace .LOCAL at end of host with .MIT.EDU if needed. */
837 hostdomain = strrchr(host, '.');
838 if (hostdomain && !strcasecmp(hostdomain, ".LOCAL"))
839 {
840 index = hostdomain - host;
841 host[index] = '\0';
842 host = realloc(host, strlen(host) + strlen(".MIT.EDU") + 1);
843 strcat(host, ".MIT.EDU");
844 }
845
846 hp = gethostbyname(host);
847 if (hp)
848 {
849 host = realloc(host, strlen(hp->h_name) + 1);
850 if (host)
851 strcpy(host, hp->h_name);
852 }
853 else
854 {
b4b129dd 855 /* Possibly a host with no A record but MX records. Check. */
856 mxrecords = getmxrecords(host);
857 if (!mxrecords)
858 return MR_BAD_MAIL_STRING;
859 else
860 return MR_SUCCESS;
7b12515f 861 }
862
863 if (!strcasecmp(host, "MIT.EDU"))
864 {
865 free(host);
866 return MR_BAD_MAIL_STRING;
867 }
868
869 EXEC SQL DECLARE csr_listmem CURSOR FOR
870 SELECT UNIQUE m.name FROM machine m, serverhosts sh
871 WHERE m.mach_id = sh.mach_id
872 AND (sh.service = 'MAILHUB' or sh.service = 'POSTOFFICE');
873 if (dbms_errno)
874 {
875 free(host);
876 return mr_errcode;
877 }
878 EXEC SQL OPEN csr_listmem;
879 if (dbms_errno)
880 {
881 free(host);
882 return mr_errcode;
883 }
884 while (1)
885 {
886 EXEC SQL FETCH csr_listmem INTO :mname;
887 if (sqlca.sqlcode)
888 break;
889
890 if (!strcasecmp(host, strtrim(mname)))
891 {
892 free(host);
893 return MR_BAD_MAIL_STRING;
894 }
895 }
896 free(host);
897 }
898
899 return MR_SUCCESS;
900}
b4b129dd 901
902/*
903 * This ought to be in the bind library. It's adapted from sendmail.
904 */
905
906/*
907 * These are defined in RFC833. Some bind interface headers don't declare them.
908 * Ghod help us if they're ever actually incompatible with what's in
909 * the arpa/nameser.h header.
910 */
911#ifndef PACKETSZ
912#define PACKETSZ 512 /* maximum packet size */
913#endif
914#ifndef HFIXEDSZ
915#define HFIXEDSZ 12 /* #/bytes of fixed data in header */
916#endif
917#ifndef INT32SZ
918#define INT32SZ 4 /* for systems without 32-bit ints */
919#endif
920#ifndef INT16SZ
921#define INT16SZ 2 /* for systems without 16-bit ints */
922#endif
923
924/* minimum possible size of MX record in packet */
925#define MIN_MX_SIZE 8 /* corresp to "a.com 0" w/ terminating space */
926
927struct mxentry *getmxrecords(const char *name)
928{
929 char answer[PACKETSZ], *eom, *cp, *bp;
930 int n, ancount, qdcount, buflen, type, pref, ind;
931 static struct mxentry pmx[(PACKETSZ - HFIXEDSZ) / MIN_MX_SIZE];
932 static char MXHostBuf[PACKETSZ - HFIXEDSZ];
933 HEADER *hp;
934
935 pmx->name = (char *)NULL;
936 pmx->pref = -1;
937 n = res_search(name, C_IN,T_MX, (unsigned char *)&answer, sizeof(answer));
938 if (n == -1)
939 return((struct mxentry *)NULL);
940 if ((size_t)n > sizeof(answer))
941 n = sizeof(answer);
942
943 hp = (HEADER *)&answer;
944 cp = answer + HFIXEDSZ;
945 eom = answer + n;
946 h_errno = 0;
947 for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ)
948 if ((n = dn_skipname((unsigned char *)cp, (unsigned char *)eom)) < 0)
949 return((struct mxentry *)NULL);
950 buflen = sizeof(MXHostBuf) - 1;
951 bp = MXHostBuf;
952 ind = 0;
953 ancount = ntohs(hp->ancount);
954 while (--ancount >= 0 && cp < eom)
955 {
956 if ((n = dn_expand((unsigned char *)answer, (unsigned char *)eom,
957 (unsigned char *)cp, bp, buflen)) < 0)
958 break;
959 cp += n;
960 GETSHORT(type, cp);
961 cp += INT16SZ + INT32SZ;
962 GETSHORT(n, cp);
963 if (type != T_MX)
964 {
965 cp += n;
966 continue;
967 }
968 GETSHORT(pref, cp);
969 if ((n = dn_expand((unsigned char *)answer, (unsigned char *)eom,
970 (unsigned char *)cp, bp, buflen)) < 0)
971 break;
972 cp += n;
973
974 pmx[ind].name = bp;
975 pmx[ind].pref = pref;
976 ++ind;
977
978 n = strlen((const char *)bp);
979 bp += n;
980 *bp++ = '\0';
981
982 buflen -= n + 1;
983 }
984
985 pmx[ind].name = (char *)NULL;
986 pmx[ind].pref = -1;
987 return(pmx);
988}
This page took 0.255471 seconds and 5 git commands to generate.