summaryrefslogtreecommitdiff
path: root/acls.c
diff options
context:
space:
mode:
authorAxel Beckert <abe@deuxchevaux.org>2011-09-03 14:05:19 +0200
committerAxel Beckert <abe@deuxchevaux.org>2011-09-03 14:05:19 +0200
commit0636e9ecb5a32db4d4520f50a20652faa825feaf (patch)
treeb94df9221e8ae0de0dc3afac301d5b63b136a7b4 /acls.c
downloadscreen-upstream/3.7.2.tar.gz
Imported Upstream version 3.7.2upstream/3.7.2
Diffstat (limited to 'acls.c')
-rw-r--r--acls.c545
1 files changed, 545 insertions, 0 deletions
diff --git a/acls.c b/acls.c
new file mode 100644
index 0000000..f13e13c
--- /dev/null
+++ b/acls.c
@@ -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 */