252 lines
5.5 KiB
C
252 lines
5.5 KiB
C
/* This file is part of the Project Athena Zephyr Notification System.
|
|
* It contains functions for dealing with acl's.
|
|
*
|
|
* Created by: John T. Kohl
|
|
*
|
|
* $Id$
|
|
*
|
|
* Copyright (c) 1987 by the Massachusetts Institute of Technology.
|
|
* For copying and distribution information, see the file
|
|
* "mit-copyright.h".
|
|
*/
|
|
|
|
#include <zephyr/mit-copyright.h>
|
|
#include "zserver.h"
|
|
|
|
#if !defined (lint) && !defined (SABER)
|
|
static const char rcsid_access_c[] =
|
|
"$Id$";
|
|
#endif
|
|
|
|
/*
|
|
*
|
|
* External routines:
|
|
*
|
|
* int access_check(sender, who, acl, accesstype)
|
|
* char *sender;
|
|
* struct sockaddr_in *who;
|
|
* Acl *acl;
|
|
* Access accesstype;
|
|
*
|
|
* int opstaff_check(sender)
|
|
* char *sender;
|
|
*
|
|
* void access_init();
|
|
*
|
|
* void access_reinit();
|
|
*/
|
|
|
|
/*
|
|
* Each restricted class has four ACL's associated with it,
|
|
* governing subscriptions, transmission, and instance restrictions.
|
|
* This module provides the 'glue' between the standard Athena ACL
|
|
* routines and the support needed by the Zephyr server.
|
|
*/
|
|
|
|
/*
|
|
* Our private types for the acl_types field in the Acl structure.
|
|
* -TYT 8/14/90
|
|
*/
|
|
#define ACL_XMT 1
|
|
#define ACL_SUB 2
|
|
#define ACL_IWS 4
|
|
#define ACL_IUI 8
|
|
|
|
static void check_acl(Acl *acl);
|
|
static void check_acl_type(Acl *acl, Access accesstype, int typeflag);
|
|
static void access_setup(int first);
|
|
|
|
/*
|
|
* check access. return 1 if ok, 0 if not ok.
|
|
*/
|
|
|
|
int
|
|
access_check(char *sender,
|
|
struct sockaddr_in *who,
|
|
Acl *acl,
|
|
Access accesstype)
|
|
{
|
|
char buf[1024]; /* holds the real acl name */
|
|
char *prefix;
|
|
int flag;
|
|
int retval;
|
|
|
|
switch (accesstype) {
|
|
case TRANSMIT:
|
|
prefix = "xmt";
|
|
flag = ACL_XMT;
|
|
break;
|
|
case SUBSCRIBE:
|
|
prefix = "sub";
|
|
flag = ACL_SUB;
|
|
break;
|
|
case INSTWILD:
|
|
prefix = "iws";
|
|
flag = ACL_IWS;
|
|
break;
|
|
case INSTUID:
|
|
prefix = "iui";
|
|
flag = ACL_IUI;
|
|
break;
|
|
default:
|
|
syslog(LOG_ERR, "unknown access type %d", (int) accesstype);
|
|
return 0;
|
|
}
|
|
if (!(acl->acl_types & flag)) /* no acl ==> no restriction */
|
|
return 1;
|
|
snprintf(buf, sizeof buf, "%s/%s-%s.acl", acl_dir, prefix, acl->acl_filename);
|
|
/*
|
|
* If we can't load it (because it probably doesn't exist),
|
|
* we deny access.
|
|
*/
|
|
retval = acl_load(buf);
|
|
if (retval < 0) {
|
|
syslog(LOG_DEBUG, "Error in acl_load of %s for %s",
|
|
buf, sender ? sender : "unauth client");
|
|
return 0;
|
|
}
|
|
return acl_check(buf, sender, who);
|
|
}
|
|
|
|
int
|
|
opstaff_check(char *sender)
|
|
{
|
|
char buf[1024]; /* holds the real acl name */
|
|
int retval;
|
|
|
|
snprintf(buf, sizeof buf, "%s/opstaff.acl", acl_dir);
|
|
/*
|
|
* If we can't load it (because it probably doesn't exist),
|
|
* we deny access.
|
|
*/
|
|
retval = acl_load(buf);
|
|
if (retval < 0) {
|
|
syslog(LOG_DEBUG, "Error in acl_load of %s for %s",
|
|
buf, sender ? sender : "unauth client");
|
|
return 0;
|
|
}
|
|
return acl_check(buf, sender, NULL);
|
|
}
|
|
|
|
static void
|
|
check_acl(Acl *acl)
|
|
{
|
|
acl->acl_types = 0;
|
|
check_acl_type(acl, TRANSMIT, ACL_XMT);
|
|
check_acl_type(acl, SUBSCRIBE, ACL_SUB);
|
|
check_acl_type(acl, INSTWILD, ACL_IWS);
|
|
check_acl_type(acl, INSTUID, ACL_IUI);
|
|
}
|
|
|
|
static void
|
|
check_acl_type(Acl *acl,
|
|
Access accesstype,
|
|
int typeflag)
|
|
{
|
|
char buf[1024]; /* holds the real acl name */
|
|
char *prefix;
|
|
|
|
switch (accesstype) {
|
|
case TRANSMIT:
|
|
prefix = "xmt";
|
|
break;
|
|
case SUBSCRIBE:
|
|
prefix = "sub";
|
|
break;
|
|
case INSTWILD:
|
|
prefix = "iws";
|
|
break;
|
|
case INSTUID:
|
|
prefix = "iui";
|
|
break;
|
|
default:
|
|
syslog(LOG_ERR, "unknown access type %d", (int) accesstype);
|
|
return;
|
|
}
|
|
snprintf(buf, sizeof buf, "%s/%s-%s.acl", acl_dir, prefix, acl->acl_filename);
|
|
if (!access(buf, F_OK))
|
|
acl->acl_types |= typeflag;
|
|
}
|
|
|
|
|
|
/*
|
|
* Re-init code written by TYT, 8/14/90.
|
|
*
|
|
* General plan of action; we reread the registry list, and add any
|
|
* new restricted classes. If any restricted classes disappear (this
|
|
* should be rarely) the Acl structure is not deallocated; rather,
|
|
* the acl_types field will be left at zero, since there will be no
|
|
* acl files for the (non-)restricted class.
|
|
*/
|
|
static void
|
|
access_setup(int first)
|
|
{
|
|
char buf[1024];
|
|
char class_name[512]; /* assume class names <= 511 bytes */
|
|
FILE *registry;
|
|
Acl *acl;
|
|
int len;
|
|
char *colon_idx;
|
|
Code_t retval = 0;
|
|
|
|
snprintf(buf, sizeof buf, "%s/%s", acl_dir, ZEPHYR_CLASS_REGISTRY);
|
|
registry = fopen(buf, "r");
|
|
if (!registry) {
|
|
syslog(LOG_ERR, "no registry available, all classes are free");
|
|
return;
|
|
}
|
|
while (fgets(class_name, 512, registry)) {
|
|
colon_idx = strchr(class_name, ':');
|
|
if (colon_idx != NULL)
|
|
*colon_idx = '\0';
|
|
else if ((len = strlen(class_name)) != 0)
|
|
class_name[len - 1] = '\0';
|
|
acl = 0;
|
|
if (!first) {
|
|
String *z;
|
|
|
|
z = make_string(class_name,1);
|
|
acl = class_get_acl(z);
|
|
free_string(z);
|
|
}
|
|
if (!acl) {
|
|
acl = (Acl *) malloc(sizeof(Acl));
|
|
if (!acl) {
|
|
syslog(LOG_ERR, "no mem acl alloc");
|
|
abort();
|
|
}
|
|
acl->acl_filename = strsave(class_name);
|
|
check_acl(acl);
|
|
|
|
if (!first) {
|
|
/* Try to restrict already existing class */
|
|
retval = class_restrict(class_name, acl);
|
|
if (retval == ZSRV_NOCLASS)
|
|
retval = class_setup_restricted(class_name, acl);
|
|
} else {
|
|
retval = class_setup_restricted(class_name, acl);
|
|
}
|
|
}
|
|
if (retval) {
|
|
syslog(LOG_ERR, "can't restrict %s: %s",
|
|
class_name, error_message(retval));
|
|
continue;
|
|
}
|
|
zdbug((LOG_DEBUG, "restricted %s", class_name));
|
|
}
|
|
fclose(registry);
|
|
}
|
|
|
|
void
|
|
access_init(void)
|
|
{
|
|
access_setup(1);
|
|
}
|
|
|
|
void
|
|
access_reinit(void)
|
|
{
|
|
acl_cache_reset();
|
|
access_setup(0);
|
|
}
|