diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2011-09-03 14:05:19 +0200 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2011-09-03 14:05:19 +0200 |
commit | 0636e9ecb5a32db4d4520f50a20652faa825feaf (patch) | |
tree | b94df9221e8ae0de0dc3afac301d5b63b136a7b4 /acls.c | |
download | screen-upstream/3.7.2.tar.gz |
Imported Upstream version 3.7.2upstream/3.7.2
Diffstat (limited to 'acls.c')
-rw-r--r-- | acls.c | 545 |
1 files changed, 545 insertions, 0 deletions
@@ -0,0 +1,545 @@ +/* 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., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + **************************************************************** + */ +#include "rcs.h" +RCS_ID("$Id: acls.c,v 1.12 1994/05/31 12:31:21 mlschroe Exp $ FAU") + +#include <sys/types.h> + +#include "config.h" +#include "screen.h" /* includes acls.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; +struct user *users; + +#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((char *)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 = &users; *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; +} + +int DefaultEsc = Ctrl('a'); +int DefaultMetaEsc = 'a'; + +/* + * Add a new user. His password may be NULL or "" if none. + * He 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 */ +#ifdef COPY_PASTE + (*up)->u_copybuffer = NULL; + (*up)->u_copylen = 0; +#endif + (*up)->u_Esc = DefaultEsc; + (*up)->u_MetaEsc = DefaultMetaEsc; + 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((char *)*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((char *)*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((char *)*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((char *)*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((char *)*up); *up = NULL; return -1; + } + maxusercount += USER_CHUNK; + } + ACLBYTE(userbits, (*up)->id) |= ACLBIT((*up)->id); + /* user id 0 is the session creator, he has all rights */ + if ((*up)->id == 0) + AclSetPerm(*up, "+rwx", "#?"); +#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. + * Destroy all his permissions and completely detach him from the session. + */ +int +UserDel(name, up) +char *name; +struct user **up; +{ + struct user *u; + struct display *old, *next; + + if (!up) + up = FindUserPtr(name); + if ((u = *up) == 0) + 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); + /* restore the bits in his slot to default: */ + AclSetPerm(u, default_w_bit[ACL_READ] ? "+r" : "-r", "#"); + AclSetPerm(u, default_w_bit[ACL_WRITE]? "+w" : "-w", "#"); + AclSetPerm(u, default_w_bit[ACL_EXEC] ? "+x" : "-x", "#"); + AclSetPerm(u, default_c_bit[ACL_EXEC] ? "+x" : "-x", "?"); +#endif + debug1("FREEING user structure for %s\n", u->u_name); +#ifdef COPY_PASTE + UserFreeCopyBuffer(u); +#endif + free((char *)u); + return 0; +} + + +#ifdef COPY_PASTE + +/* + * returns 0 if the copy buffer was really deleted. + * Also removes any references into the users copybuffer + */ +int +UserFreeCopyBuffer(u) +struct user *u; +{ + struct win *w; + + if (!u->u_copybuffer) + return 1; + for (w = windows; w; w = w->w_next) + { + if (w->w_pasteptr >= u->u_copybuffer && + w->w_pasteptr - u->u_copybuffer < u->u_copylen) + { + if (w->w_pastebuf) + free(w->w_pastebuf); + w->w_pastebuf = 0; + w->w_pasteptr = 0; + w->w_pastelen = 0; + } + } + free(u->u_copybuffer); + D_user->u_copylen = 0; + u->u_copybuffer = NULL; + return 0; +} + +#endif /* COPY_PASTE */ + +/************************************************************************ + * 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((char *)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 */ +/* + * aclchg nerd -w+w 2 + * releases a writelock on window 2 held by user nerd. + */ +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); + if ((win->w_wlockuser == u) && neg && (bit == ACL_WRITE)) + { + debug2("%s lost writelock on win %d\n", u->u_name, win->w_number); + win->w_wlockuser = NULL; + if (win->w_wlock == WLOCK_ON) + win->w_wlock = WLOCK_AUTO; + } + } + 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, ch; + + 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 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 ((ch = *p) != 0) + *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; + if (ch) + p[-1] = ch; + 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 */ |