home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume26
/
screen-3.5
/
part02
/
acl.c
next >
Wrap
C/C++ Source or Header
|
1993-07-25
|
11KB
|
479 lines
/* Copyright (c) 1993
* Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
* Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
* Copyright (c) 1987 Oliver Laumann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see the file COPYING); if not, write to the
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
****************************************************************
*/
#include "rcs.h"
RCS_ID("$Id: acl.c,v 1.5 1993/07/16 14:04:12 mlschroe Exp $ FAU")
#include "config.h"
#include "screen.h" /* includes acl.h */
#include "extern.h"
/************************************************************************
* user managing code, this does not really belong into the acl stuff *
************************************************************************/
extern struct comm comms[];
extern struct win *windows, *wtab[];
extern struct display *display, *displays;
static struct user *userroot;
#ifdef MULTIUSER
/* record given user ids here */
static AclBits userbits;
/* rights a new unknown user will have on windows and cmds */
static char default_w_bit[ACL_BITS_PER_WIN] =
{
1, /* EXEC */
1, /* WRITE */
1 /* READ */
};
static char default_c_bit[ACL_BITS_PER_CMD] =
{
1 /* EXEC */
};
/* rights of all users per newly created window */
static AclBits default_w_userbits[ACL_BITS_PER_WIN];
/*
static AclBits default_c_userbits[ACL_BITS_PER_CMD];
*/
static int maxusercount = 0;
static int GrowBitfield __P((AclBits *, int, int, int));
static int
GrowBitfield(bfp, len, delta, defaultbit)
AclBits *bfp;
int len, delta, defaultbit;
{
AclBits n, o = *bfp;
int i;
if (!(n = (AclBits)calloc(1, (unsigned long)(&ACLBYTE((char *)0, len + delta + 1)))))
return -1;
for (i = 0; i < (len + delta); i++)
{
if (((i < len) && (ACLBIT(i) & ACLBYTE(o, i))) ||
((i >= len) && (defaultbit)))
ACLBYTE(n, i) |= ACLBIT(i);
}
if (len)
free(o);
*bfp = n;
return 0;
}
#endif /* MULTIUSER */
/*
* Returns an nonzero Address. Its contents is either a User-ptr,
* or NULL which may be replaced by a User-ptr to create the entry.
*/
struct user **
FindUserPtr(name)
char *name;
{
struct user **u;
for (u = &userroot; *u; u = &(*u)->u_next)
if (!strcmp((*u)->u_name, name))
break;
#ifdef MULTIUSER
debug3("FindUserPtr %s %sfound, id %d\n", name, (*u)?"":"not ",
(*u)?(*u)->id:-1);
#else
debug2("FindUserPtr %s %sfound\n", name, (*u)?"":"not ");
#endif
return u;
}
/*
* Add a new user. His password may be NULL or "" if none.
* He is in no groups and thus has no rights.
*/
int
UserAdd(name, pass, up)
char *name, *pass;
struct user **up;
{
if (!up)
up = FindUserPtr(name);
if (*up)
return 1; /* he is already there */
*up = (struct user *)calloc(1, sizeof(struct user));
if (!*up)
return -1; /* he still does not exist */
strncpy((*up)->u_name, name, 20);
if (pass)
strncpy((*up)->u_password, pass, 20);
#ifdef MULTIUSER
/* now find an unused index */
for ((*up)->id = 0; (*up)->id < maxusercount; (*up)->id++)
if (!(ACLBIT((*up)->id) & ACLBYTE(userbits, (*up)->id)))
break;
debug2("UserAdd %s id %d\n", name, (*up)->id);
if ((*up)->id == maxusercount)
{
int i, j;
struct win *w;
debug2("growing all bitfields %d += %d\n", maxusercount, USER_CHUNK);
/* the bitfields are full, grow a chunk */
/* first, the used_uid_indicator: */
if (GrowBitfield(&userbits, maxusercount, USER_CHUNK, 0))
{
free(*up); *up = NULL; return -1;
}
/* second, default command bits */
/* (only if we generate commands dynamically) */
/*
for (j = 0; j < ACL_BITS_PER_CMD; j++)
if (GrowBitfield(&default_c_userbits[j], maxusercount, USER_CHUNK,
default_c_bit[j]))
{
free(*up); *up = NULL; return -1;
}
*/
/* third, the bits for each commands */
for (i = 0; i <= RC_LAST; i++)
for (j = 0; j < ACL_BITS_PER_CMD; j++)
if (GrowBitfield(&comms[i].userbits[j], maxusercount, USER_CHUNK,
default_c_bit[j]))
{
free(*up); *up = NULL; return -1;
}
/* fourth, default window and bits */
for (j = 0; j < ACL_BITS_PER_WIN; j++)
if (GrowBitfield(&default_w_userbits[j], maxusercount, USER_CHUNK,
default_w_bit[j]))
{
free(*up); *up = NULL; return -1;
}
/* fifth, the bits for each window */
for (w = windows; w; w = w->w_next)
for (j = 0; j < ACL_BITS_PER_WIN; j++)
if (GrowBitfield(&w->w_userbits[j], maxusercount, USER_CHUNK,
default_w_bit[j]))
{
free(*up); *up = NULL; return -1;
}
maxusercount += USER_CHUNK;
}
ACLBYTE(userbits, (*up)->id) |= ACLBIT((*up)->id);
#else /* MULTIUSER */
debug1("UserAdd %s\n", name);
#endif /* MULTIUSER */
return 0;
}
/* change user's password */
int
UserSetPass(name, pass, up)
char *name, *pass;
struct user **up;
{
if (!up)
up = FindUserPtr(name);
if (!*up)
return UserAdd(name, pass, up);
strncpy((*up)->u_password, pass ? pass : "", 20);
(*up)->u_password[20] = '\0';
return 0;
}
/*
* Remove a user from the list.
* Decrease reference count of all his groups
* Free his grouplist.
*/
int
UserDel(name, up)
char *name;
struct user **up;
{
struct user *u;
struct display *old, *next;
if (!up)
up = FindUserPtr(name);
if (!(u = *up))
return -1; /* he who does not exist cannot be removed */
old = display;
for (display = displays; display; display = next)
{
next = display->_d_next;
if (d_user != u)
continue;
if (display == old)
old = 0;
Detach(D_REMOTE);
}
display = old;
*up = u->u_next;
#ifdef MULTIUSER
ACLBYTE(userbits, u->id) &= ~ACLBIT(u->id);
AclSetPerm(u, "-rwx", "#?");
#endif
debug1("FREEING user structure for %s\n", u->u_name);
free(u);
return 0;
}
/************************************************************************
* end of user managing code *
************************************************************************/
#ifdef MULTIUSER
extern char *multi; /* username */
/* This gives the users default rights to the new window */
int
NewWindowAcl(w)
struct win *w;
{
int i, j;
debug1("NewWindowAcl default_w_userbits for window %d\n", w->w_number);
for (j = 0; j < ACL_BITS_PER_WIN; j++)
{
/* we start with len 0 for the new bitfield size and add maxusercount */
if (GrowBitfield(&w->w_userbits[j], 0, maxusercount, 0))
{
while (--j >= 0)
free(w->w_userbits[j]);
return -1;
}
for (i = 0; i < maxusercount; i++)
if (ACLBIT(i) & ACLBYTE(default_w_userbits[j], i))
ACLBYTE(w->w_userbits[j], i) |= ACLBIT(i);
}
return 0;
}
/* if mode starts with '-' we remove the users exec bit for cmd */
int
AclSetPermCmd(u, mode, cmd)
struct user *u;
char *mode;
struct comm *cmd;
{
int neg = 0;
if (!multi)
return 0;
debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name);
while (*mode)
{
switch (*mode++)
{
case '-':
neg = 1;
continue;
case '+':
neg = 0;
continue;
case 'e':
case 'x':
if (neg)
ACLBYTE(cmd->userbits[ACL_EXEC], u->id) &= ~ACLBIT(u->id);
else
ACLBYTE(cmd->userbits[ACL_EXEC], u->id) |= ACLBIT(u->id);
break;
case 'r':
case 'w':
break;
default:
return -1;
}
}
return 0;
}
/* mode strings of the form +rwx -w+rx r -wx are parsed and evaluated */
int
AclSetPermWin(u, mode, win)
struct user *u;
char *mode;
struct win *win;
{
int neg = 0;
int bit;
if (!multi)
return 0;
debug3("AclSetPermWin %s %s %d\n", u->u_name, mode, win->w_number);
while (*mode)
{
switch (*mode++)
{
case '-':
neg = 1;
continue;
case '+':
neg = 0;
continue;
case 'r':
bit = ACL_READ;
break;
case 'w':
bit = ACL_WRITE;
break;
case 'x':
bit = ACL_EXEC;
break;
default:
return -1;
}
if (neg)
ACLBYTE(win->w_userbits[bit], u->id) &= ~ACLBIT(u->id);
else
ACLBYTE(win->w_userbits[bit], u->id) |= ACLBIT(u->id);
}
return 0;
}
/* string is broken down into comand and window names, mode applies */
int
AclSetPerm(u, mode, s)
struct user *u;
char *mode, *s;
{
struct win *w;
int i;
char *p;
while (*s)
{
switch (*s)
{
case '*': /* all windows and all commands */
return AclSetPerm(u, mode, "#?");
case '#': /* all windows */
for (w = windows; w; w = w->w_next)
AclSetPermWin(u, mode, w);
s++;
break;
case '?': /* all windows and all commands */
for (i = 0; i <= RC_LAST; i++)
AclSetPermCmd(u, mode, &comms[i]);
s++;
break;
default:
for (p = s; *p && *p != ' ' && *p != '\t' && *p != ','; p++)
;
if (*p)
*p++ = '\0';
else
*p = '\0';
if ((i = FindCommnr(s)) != RC_ILLEGAL)
AclSetPermCmd(u, mode, &comms[i]);
else if (((i = WindowByNoN(s)) >= 0) && wtab[i])
AclSetPermWin(u, mode, wtab[i]);
else
/* checking group name */
return -1;
s = p;
}
}
return 0;
}
#if 0
void
AclWinSwap(a, b)
int a, b;
{
int a_bit = 0, b_bit = 0;
AclGroupList **g;
AclBits p;
debug2("acl lists swapping windows %d and %d\n", a, b);
for (g = &aclgrouproot; *g; g = &(*g)->next)
{
p = (*g)->group->winbits;
/* see if there was a bit for window a. zap it */
if (a >= 0)
if ((a_bit = ACLBIT(a) & ACLBYTE(p, a)))
ACLBYTE(p, a) &= ~ACLBIT(a);
/* see if there was a bit for window b. zap it */
if (b >= 0)
if ((b_bit = ACLBIT(b) & ACLBYTE(p, b)))
ACLBYTE(p, b) &= ~ACLBIT(b);
/* b may cause a set */
if (b_bit && a >= 0)
ACLBYTE(p, a) |= ACLBIT(a);
/* a may cause b set */
if (a_bit && b >= 0)
ACLBYTE(p, b) |= ACLBIT(b);
}
}
#else
void
AclWinSwap(a, b)
int a, b;
{
debug2("AclWinSwap(%d, %d) DUMMY\n", a, b);
}
#endif
int
AclCheckPermWin(u, mode, w)
struct user *u;
int mode;
struct win *w;
{
if (!multi)
return 0;
if (mode < 0 || mode >= ACL_BITS_PER_WIN)
return -1;
debug3("AclCheckPermWin(%s, %d, %d) = ", u->u_name, mode, w->w_number);
debug1("%d\n", !(ACLBYTE(w->w_userbits[mode], u->id) & ACLBIT(u->id)));
return !(ACLBYTE(w->w_userbits[mode], u->id) & ACLBIT(u->id));
}
int
AclCheckPermCmd(u, mode, c)
struct user *u;
int mode;
struct comm *c;
{
if (!multi)
return 0;
if (mode < 0 || mode >= ACL_BITS_PER_CMD)
return -1;
debug3("AclCheckPermCmd(%s %d %s) = ", u->u_name, mode, c->name);
debug1("%d\n", !(ACLBYTE(c->userbits[mode], u->id) & ACLBIT(u->id)));
return !(ACLBYTE(c->userbits[mode], u->id) & ACLBIT(u->id));
}
#endif /* MULTIUSER */