diff options
Diffstat (limited to 'acls.c')
-rw-r--r-- | acls.c | 610 |
1 files changed, 479 insertions, 131 deletions
@@ -36,34 +36,38 @@ RCS_ID("$Id: acls.c,v 1.12 1994/05/31 12:31:21 mlschroe Exp $ FAU") extern struct comm comms[]; extern struct win *windows, *wtab[]; +extern char NullStr[]; extern struct display *display, *displays; struct user *users; #ifdef MULTIUSER +int maxusercount = 0; /* used in process.c: RC_MONITOR, RC_SILENCE */ + /* record given user ids here */ static AclBits userbits; -/* rights a new unknown user will have on windows and cmds */ +/* + * rights a new unknown user will have on windows and cmds. + * These are changed by a "umask ?-..." command: + */ static char default_w_bit[ACL_BITS_PER_WIN] = { - 1, /* EXEC */ - 1, /* WRITE */ - 1 /* READ */ + 0, /* EXEC */ + 0, /* WRITE */ + 0 /* READ */ }; static char default_c_bit[ACL_BITS_PER_CMD] = { - 1 /* EXEC */ + 0 /* 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; + * are now stored per user (umask) + * static AclBits default_w_userbits[ACL_BITS_PER_WIN]; + * static AclBits default_c_userbits[ACL_BITS_PER_CMD]; + */ static int GrowBitfield __P((AclBits *, int, int, int)); @@ -108,30 +112,40 @@ char *name; break; #ifdef MULTIUSER debug3("FindUserPtr %s %sfound, id %d\n", name, (*u)?"":"not ", - (*u)?(*u)->id:-1); -#else + (*u)?(*u)->u_id:-1); +#else /* MULTIUSER */ debug2("FindUserPtr %s %sfound\n", name, (*u)?"":"not "); -#endif +#endif /* MULTIUSER */ return u; } -int DefaultEsc = Ctrl('a'); -int DefaultMetaEsc = 'a'; +int DefaultEsc = -1; /* initialised by screen.c:main() */ +int DefaultMetaEsc = -1; /* - * Add a new user. His password may be NULL or "" if none. - * He has no rights. + * Add a new user. His password may be NULL or "" if none. His name must not + * be "none", as this represents the NULL-pointer when dealing with groups. + * He has default rights, determined by umask. */ int UserAdd(name, pass, up) char *name, *pass; struct user **up; { +#ifdef MULTIUSER + int j; +#endif + if (!up) up = FindUserPtr(name); if (*up) - return 1; /* he is already there */ - *up = (struct user *)calloc(1, sizeof(struct user)); + { + if (pass) + (*up)->u_password = SaveStr(pass); + return 1; /* he is already there */ + } + if (strcmp("none", name)) /* "none" is a reserved word */ + *up = (struct user *)calloc(1, sizeof(struct user)); if (!*up) return -1; /* he still does not exist */ #ifdef COPY_PASTE @@ -141,19 +155,24 @@ struct user **up; (*up)->u_Esc = DefaultEsc; (*up)->u_MetaEsc = DefaultMetaEsc; strncpy((*up)->u_name, name, 20); + (*up)->u_password = NULL; if (pass) - strncpy((*up)->u_password, pass, 20); + (*up)->u_password = SaveStr(pass); + if (!(*up)->u_password) + (*up)->u_password = NullStr; #ifdef MULTIUSER + (*up)->u_group = NULL; /* now find an unused index */ - for ((*up)->id = 0; (*up)->id < maxusercount; (*up)->id++) - if (!(ACLBIT((*up)->id) & ACLBYTE(userbits, (*up)->id))) + for ((*up)->u_id = 0; (*up)->u_id < maxusercount; (*up)->u_id++) + if (!(ACLBIT((*up)->u_id) & ACLBYTE(userbits, (*up)->u_id))) break; - debug2("UserAdd %s id %d\n", name, (*up)->id); - if ((*up)->id == maxusercount) + debug2("UserAdd %s id %d\n", name, (*up)->u_id); + if ((*up)->u_id == maxusercount) { - int i, j; + int j; struct win *w; + struct user *u; debug2("growing all bitfields %d += %d\n", maxusercount, USER_CHUNK); /* the bitfields are full, grow a chunk */ @@ -173,55 +192,89 @@ struct user **up; } */ /* 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])) + for (j = 0; j <= RC_LAST; j++) + { + int i; + + for (i = 0; i < ACL_BITS_PER_CMD; i++) + if (GrowBitfield(&comms[j].userbits[i], maxusercount, USER_CHUNK, + default_c_bit[i])) + { + free((char *)*up); *up = NULL; return -1; + } + } + /* fourth, default window creation bits per user */ + for (u = users; u != *up; u = u->u_next) + { + for (j = 0; j < ACL_BITS_PER_WIN; j++) { - free((char *)*up); *up = NULL; return -1; + if (GrowBitfield(&u->u_umask_w_bits[j], maxusercount, USER_CHUNK, + default_w_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 */ + /* keep these in sync with NewWindowAcl() */ 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; + { + /* five a: the access control list */ + 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; + } + /* five b: the activity notify list */ + /* five c: the silence notify list */ + if (GrowBitfield(&w->w_mon_notify, maxusercount, USER_CHUNK, 0) || + GrowBitfield(&w->w_lio_notify, maxusercount, USER_CHUNK, 0)) + { + free((char *)*up); *up = NULL; return -1; } + } maxusercount += USER_CHUNK; } - ACLBYTE(userbits, (*up)->id) |= ACLBIT((*up)->id); + + /* mark the user-entry as "in-use" */ + ACLBYTE(userbits, (*up)->u_id) |= ACLBIT((*up)->u_id); + /* user id 0 is the session creator, he has all rights */ - if ((*up)->id == 0) - AclSetPerm(*up, "+rwx", "#?"); + if ((*up)->u_id == 0) + AclSetPerm(NULL, *up, "+a", "#?"); + + /* user nobody has a fixed set of rights: */ + if (!strcmp((*up)->u_name, "nobody")) + { + AclSetPerm(NULL, *up, "-rwx", "#?"); + AclSetPerm(NULL, *up, "+x", "su"); + AclSetPerm(NULL, *up, "+x", "detach"); + AclSetPerm(NULL, *up, "+x", "displays"); + AclSetPerm(NULL, *up, "+x", "version"); + } + + /* + * Create his umask: + * Give default_w_bit's for all users, + * but allow himself everything on "his" windows. + */ + for (j = 0; j < ACL_BITS_PER_WIN; j++) + { + if (GrowBitfield(&(*up)->u_umask_w_bits[j], 0, maxusercount, + default_w_bit[j])) + { + free((char *)*up); *up = NULL; return -1; + } + ACLBYTE((*up)->u_umask_w_bits[j], (*up)->u_id) |= ACLBIT((*up)->u_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. * Destroy all his permissions and completely detach him from the session. @@ -232,37 +285,66 @@ char *name; struct user **up; { struct user *u; +#ifdef MULTIUSER + int i; +#endif struct display *old, *next; if (!up) up = FindUserPtr(name); - if ((u = *up) == 0) + 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; + next = display->d_next; /* read the next ptr now, Detach may zap it. */ if (D_user != u) continue; if (display == old) - old = 0; + old = NULL; Detach(D_REMOTE); } display = old; *up = u->u_next; + #ifdef MULTIUSER - ACLBYTE(userbits, u->id) &= ~ACLBIT(u->id); + for (up = &users; *up; up = &(*up)->u_next) + { + /* unlink all group references to this user */ + struct usergroup **g = &(*up)->u_group; + + while (*g) + { + if ((*g)->u == u) + { + struct usergroup *next = (*g)->next; + + free((char *)(*g)); + *g = next; + } + else + g = &(*g)->next; + } + } + ACLBYTE(userbits, u->u_id) &= ~ACLBIT(u->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 + AclSetPerm(NULL, u, default_w_bit[ACL_READ] ? "+r" : "-r", "#"); + AclSetPerm(NULL, u, default_w_bit[ACL_WRITE]? "+w" : "-w", "#"); + AclSetPerm(NULL, u, default_w_bit[ACL_EXEC] ? "+x" : "-x", "#"); + AclSetPerm(NULL, u, default_c_bit[ACL_EXEC] ? "+x" : "-x", "?"); + for (i = 0; i < ACL_BITS_PER_WIN; i++) + free((char *)u->u_umask_w_bits[i]); +#endif /* MULTIUSER */ debug1("FREEING user structure for %s\n", u->u_name); #ifdef COPY_PASTE UserFreeCopyBuffer(u); #endif free((char *)u); + if (!users) + { + debug("Last user deleted. Feierabend.\n"); + Finit(0); /* Destroying whole session. Noone could ever attach again. */ + } return 0; } @@ -287,18 +369,17 @@ struct user *u; w->w_pasteptr - u->u_copybuffer < u->u_copylen) { if (w->w_pastebuf) - free(w->w_pastebuf); + free((char *)w->w_pastebuf); w->w_pastebuf = 0; w->w_pasteptr = 0; w->w_pastelen = 0; } } - free(u->u_copybuffer); - D_user->u_copylen = 0; + free((char *)u->u_copybuffer); + u->u_copylen = 0; u->u_copybuffer = NULL; return 0; } - #endif /* COPY_PASTE */ /************************************************************************ @@ -308,16 +389,21 @@ struct user *u; #ifdef MULTIUSER -extern char *multi; /* username */ - -/* This gives the users default rights to the new window */ +/* This gives the users default rights to the new window w created by u */ int -NewWindowAcl(w) +NewWindowAcl(w, u) struct win *w; +struct user *u; { int i, j; - debug1("NewWindowAcl default_w_userbits for window %d\n", w->w_number); + debug2("NewWindowAcl %s's umask_w_bits for window %d\n", + u ? u->u_name : "everybody", w->w_number); + + /* keep these in sync with UserAdd part five. */ + if (GrowBitfield(&w->w_mon_notify, 0, maxusercount, 0) || + GrowBitfield(&w->w_lio_notify, 0, maxusercount, 0)) + return -1; for (j = 0; j < ACL_BITS_PER_WIN; j++) { /* we start with len 0 for the new bitfield size and add maxusercount */ @@ -328,27 +414,30 @@ struct win *w; return -1; } for (i = 0; i < maxusercount; i++) - if (ACLBIT(i) & ACLBYTE(default_w_userbits[j], i)) + if (u ? (ACLBIT(i) & ACLBYTE(u->u_umask_w_bits[j], i)) : + default_w_bit[j]) ACLBYTE(w->w_userbits[j], i) |= ACLBIT(i); } return 0; } /* if mode starts with '-' we remove the users exec bit for cmd */ -int +/* + * NOTE: before you make this function look the same as + * AclSetPermWin, try to merge both functions. + */ +static int AclSetPermCmd(u, mode, cmd) struct user *u; char *mode; struct comm *cmd; { int neg = 0; + char *m = mode; - if (!multi) - return 0; - debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name); - while (*mode) + while (*m) { - switch (*mode++) + switch (*m++) { case '-': neg = 1; @@ -356,12 +445,14 @@ struct comm *cmd; case '+': neg = 0; continue; + case 'a': case 'e': case 'x': +/* debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name); */ if (neg) - ACLBYTE(cmd->userbits[ACL_EXEC], u->id) &= ~ACLBIT(u->id); + ACLBYTE(cmd->userbits[ACL_EXEC], u->u_id) &= ~ACLBIT(u->u_id); else - ACLBYTE(cmd->userbits[ACL_EXEC], u->id) |= ACLBIT(u->id); + ACLBYTE(cmd->userbits[ACL_EXEC], u->u_id) |= ACLBIT(u->u_id); break; case 'r': case 'w': @@ -377,22 +468,35 @@ struct comm *cmd; /* * aclchg nerd -w+w 2 * releases a writelock on window 2 held by user nerd. + * Letter n allows network access on a window. + * uu should be NULL, except if you want to change his umask. */ -int -AclSetPermWin(u, mode, win) -struct user *u; +static int +AclSetPermWin(uu, u, mode, win) +struct user *u, *uu; char *mode; struct win *win; { int neg = 0; - int bit; + int bit, bits; + AclBits *bitarray; + char *m = mode; + + if (uu) + { + debug3("AclSetPermWin %s UMASK %s %s\n", uu->u_name, u->u_name, mode); + bitarray = uu->u_umask_w_bits; + } + else + { + ASSERT(win); + bitarray = win->w_userbits; + debug3("AclSetPermWin %s %s %d\n", u->u_name, mode, win->w_number); + } - if (!multi) - return 0; - debug3("AclSetPermWin %s %s %d\n", u->u_name, mode, win->w_number); - while (*mode) + while (*m) { - switch (*mode++) + switch (*m++) { case '-': neg = 1; @@ -401,67 +505,114 @@ struct win *win; neg = 0; continue; case 'r': - bit = ACL_READ; + bits = (1 << ACL_READ); break; case 'w': - bit = ACL_WRITE; + bits = (1 << ACL_WRITE); break; case 'x': - bit = ACL_EXEC; + bits = (1 << ACL_EXEC); + break; + case 'a': + bits = (1 << ACL_BITS_PER_WIN) - 1; 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)) + for (bit = 0; bit < ACL_BITS_PER_WIN; bit++) + { + if (!(bits & (1 << bit))) + continue; + if (neg) + ACLBYTE(bitarray[bit], u->u_id) &= ~ACLBIT(u->u_id); + else + ACLBYTE(bitarray[bit], u->u_id) |= ACLBIT(u->u_id); + if (!uu && (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; + } + } + } + if (uu && u->u_name[0] == '?' && u->u_name[1] == '\0') + { + /* + * It is Mr. '?', the unknown user. He deserves special treatment as + * he defines the defaults. Sorry, this is global, not per user. + */ + if (win) { - 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; - } + debug1("AclSetPermWin: default_w_bits '%s'.\n", mode); + for (bit = 0; bit < ACL_BITS_PER_WIN; bit++) + default_w_bit[bit] = + (ACLBYTE(bitarray[bit], u->u_id) & ACLBIT(u->u_id)) ? 1 : 0; + } + else + { + /* + * Hack. I do not want to duplicate all the above code for + * AclSetPermCmd. This asumes that there are not more bits + * per cmd than per win. + */ + debug1("AclSetPermWin: default_c_bits '%s'.\n", mode); + for (bit = 0; bit < ACL_BITS_PER_CMD; bit++) + default_c_bit[bit] = + (ACLBYTE(bitarray[bit], u->u_id) & ACLBIT(u->u_id)) ? 1 : 0; + } + UserDel(u->u_name, NULL); } return 0; } -/* string is broken down into comand and window names, mode applies */ +/* + * String is broken down into comand and window names, mode applies + * A command name matches first, so do not use these as window names. + * uu should be NULL, except if you want to change his umask. + */ int -AclSetPerm(u, mode, s) -struct user *u; +AclSetPerm(uu, u, mode, s) +struct user *uu, *u; char *mode, *s; { struct win *w; int i; char *p, ch; + debug3("AclSetPerm(uu, user '%s', mode '%s', object '%s')\n", + u->u_name, mode, s); 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); + case '*': /* all windows and all commands */ + return AclSetPerm(uu, u, mode, "#?"); + case '#': + if (uu) /* window umask or .. */ + AclSetPermWin(uu, u, mode, (struct win *)1); + else /* .. or all windows */ + for (w = windows; w; w = w->w_next) + AclSetPermWin(NULL, u, mode, w); s++; break; - case '?': /* all commands */ - for (i = 0; i <= RC_LAST; i++) - AclSetPermCmd(u, mode, &comms[i]); + case '?': + if (uu) /* command umask or .. */ + AclSetPermWin(uu, u, mode, (struct win *)0); + else /* .. or 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) + if ((ch = *p)) *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]); + AclSetPermWin(NULL, u, mode, wtab[i]); else /* checking group name */ return -1; @@ -473,6 +624,156 @@ char *mode, *s; return 0; } +/* + * Generic ACL Manager: + * + * This handles acladd and aclchg identical. + * With 2 or 4 parameters, the second parameter is a password. + * With 3 or 4 parameters the last two parameters specify the permissions + * else user is added with full permissions. + * With 1 parameter the users permissions are copied from user *argv. + * Unlike the other cases, u->u_name should not match *argv here. + * uu should be NULL, except if you want to change his umask. + */ +static int +UserAcl(uu, u, argc, argv) +struct user *uu, **u; +int argc; +char **argv; +{ + if ((*u && !strcmp((*u)->u_name, "nobody")) || + (argc > 1 && !strcmp(argv[0], "nobody"))) + return -1; /* do not change nobody! */ + + switch (argc) + { + case 1+1+2: + debug2("UserAcl: user '%s', password '%s':", argv[0], argv[1]); + return (UserAdd(argv[0], argv[1], u) < 0) || + AclSetPerm(uu, *u, argv[2], argv[3]); + case 1+2: + debug1("UserAcl: user '%s', no password:", argv[0]); + return (UserAdd(argv[0], NULL, u) < 0) || + AclSetPerm(uu, *u, argv[1], argv[2]); + case 1+1: + debug2("UserAcl: user '%s', password '%s'\n", argv[0], argv[1]); + return UserAdd(argv[0], argv[1], u) < 0; + case 1: + debug1("UserAcl: user '%s', no password:", argv[0]); + return (UserAdd(argv[0], NULL, u) < 0) || + AclSetPerm(uu, *u, "+a", "#?"); + default: + return -1; + } +} + +static int +UserAclCopy(to_up, from_up) +struct user **to_up, **from_up; +{ + struct win *w; + int i, j, to_id, from_id; + + if (!*to_up || !*from_up) + return -1; + debug2("UserAclCopy: from user '%s' to user '%s'\n", + (*from_up)->u_name, (*to_up)->u_name); + if ((to_id = (*to_up)->u_id) == (from_id = (*from_up)->u_id)) + return -1; + for (w = windows; w; w = w->w_next) + { + for (i = 0; i < ACL_BITS_PER_WIN; i++) + { + if (ACLBYTE(w->w_userbits[i], from_id) & ACLBIT(from_id)) + ACLBYTE(w->w_userbits[i], to_id) |= ACLBIT(to_id); + else + { + ACLBYTE(w->w_userbits[i], to_id) &= ~ACLBIT(to_id); + if ((w->w_wlockuser == *to_up) && (i == ACL_WRITE)) + { + debug2("%s lost wlock on win %d\n", + (*to_up)->u_name, w->w_number); + w->w_wlockuser = NULL; + if (w->w_wlock == WLOCK_ON) + w->w_wlock = WLOCK_AUTO; + } + } + } + } + for (j = 0; j <= RC_LAST; j++) + { + for (i = 0; i < ACL_BITS_PER_CMD; i++) + { + if (ACLBYTE(comms[j].userbits[i], from_id) & ACLBIT(from_id)) + ACLBYTE(comms[j].userbits[i], to_id) |= ACLBIT(to_id); + else + ACLBYTE(comms[j].userbits[i], to_id) &= ~ACLBIT(to_id); + } + } + + return 0; +} + +/* + * Syntax: + * user [password] [+rwx #?] + * * [password] [+rwx #?] + * user1,user2,user3 [password] [+rwx #?] + * user1,user2,user3=user + * uu should be NULL, except if you want to change his umask. + */ +int +UsersAcl(uu, argc, argv) +struct user *uu; +int argc; +char **argv; +{ + char *s; + int r; + struct user **cf_u = NULL; + + if (argc == 1) + { + char *p = NULL; + + s = argv[0]; + while (*s) + if (*s++ == '=') p = s; + if (p) + { + p[-1] = '\0'; + cf_u = FindUserPtr(p); + } + } + + if (argv[0][0] == '*' && argv[0][1] == '\0') + { + struct user **u; + + debug("all users acls.\n"); + for (u = &users; *u; u = &(*u)->u_next) + if (strcmp("nobody", (*u)->u_name) && + ((cf_u) ? + ((r = UserAclCopy(u, cf_u)) < 0) : + ((r = UserAcl(uu, u, argc, argv)) < 0))) + return -1; + return 0; + } + + do + { + for (s = argv[0]; *s && *s!=' ' && *s!='\t' && *s!=',' && *s!='='; s++) + ; + *s ? (*s++ = '\0') : (*s = '\0'); + debug2("UsersAcl(uu, \"%s\", argc=%d)\n", argv[0], argc); + if ((cf_u) ? + ((r = UserAclCopy(FindUserPtr(argv[0]), cf_u)) < 0) : + ((r = UserAcl(uu, FindUserPtr(argv[0]), argc, argv)) < 0)) + return -1; + } while (*(argv[0] = s)); + return 0; +} + #if 0 void AclWinSwap(a, b) @@ -512,19 +813,44 @@ int a, b; } #endif +struct user *EffectiveAclUser = NULL; /* hook for AT command permission */ + int AclCheckPermWin(u, mode, w) struct user *u; int mode; struct win *w; { - if (!multi) - return 0; + int ok; + if (mode < 0 || mode >= ACL_BITS_PER_WIN) return -1; + if (EffectiveAclUser) + { + debug1("AclCheckPermWin: WARNING user %s overridden!\n", u->u_name); + u = EffectiveAclUser; + } + ok = ACLBYTE(w->w_userbits[mode], u->u_id) & ACLBIT(u->u_id); 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)); + + if (!ok) + { + struct usergroup **g = &u->u_group; + struct user *saved_eff = EffectiveAclUser; + + EffectiveAclUser = NULL; + while (*g) + { + if (!AclCheckPermWin((*g)->u, mode, w)) + break; + g = &(*g)->next; + } + EffectiveAclUser = saved_eff; + if (*g) + ok = 1; + } + debug1("%d\n", !ok); + return !ok; } int @@ -533,13 +859,35 @@ struct user *u; int mode; struct comm *c; { - if (!multi) - return 0; + int ok; + if (mode < 0 || mode >= ACL_BITS_PER_CMD) return -1; + if (EffectiveAclUser) + { + debug1("AclCheckPermCmd: WARNING user %s overridden!\n", u->u_name); + u = EffectiveAclUser; + } + ok = ACLBYTE(c->userbits[mode], u->u_id) & ACLBIT(u->u_id); 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)); + if (!ok) + { + struct usergroup **g = &u->u_group; + struct user *saved_eff = EffectiveAclUser; + + EffectiveAclUser = NULL; + while (*g) + { + if (!AclCheckPermCmd((*g)->u, mode, c)) + break; + g = &(*g)->next; + } + EffectiveAclUser = saved_eff; + if (*g) + ok = 1; + } + debug1("%d\n", !ok); + return !ok; } #endif /* MULTIUSER */ |