1 /* Copyright (c) 2008, 2009
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Micah Cowan (micah@cowan.name)
5 * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6 * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9 * Copyright (c) 1987 Oliver Laumann
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3, or (at your option)
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program (see the file COPYING); if not, see
23 * http://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 ****************************************************************
29 #include <sys/types.h>
34 /* XXX: WHY IS THIS HERE?? :XXX */
38 # include <stdio.h> /* needed by <pwd.h> */
39 # endif /* _SEQUENT_ */
43 # endif /* SHADOWPW */
44 #endif /* CHECKLOGIN */
50 #include "screen.h" /* includes acls.h */
54 /************************************************************************
55 * user managing code, this does not really belong into the acl stuff *
56 ************************************************************************/
58 extern struct comm comms
[];
59 extern struct win
*windows
, *wtab
[];
60 extern char NullStr
[];
61 extern char SockPath
[];
62 extern struct display
*display
, *displays
;
63 struct acluser
*users
;
66 int maxusercount
= 0; /* used in process.c: RC_MONITOR, RC_SILENCE */
68 /* record given user ids here */
69 static AclBits userbits
;
72 * rights a new unknown user will have on windows and cmds.
73 * These are changed by a "umask ?-..." command:
75 static char default_w_bit
[ACL_BITS_PER_WIN
] =
82 static char default_c_bit
[ACL_BITS_PER_CMD
] =
87 /* rights of all users per newly created window */
89 * are now stored per user (umask)
90 * static AclBits default_w_userbits[ACL_BITS_PER_WIN];
91 * static AclBits default_c_userbits[ACL_BITS_PER_CMD];
94 static int GrowBitfield
__P((AclBits
*, int, int, int));
95 static struct aclusergroup
**FindGroupPtr
__P((struct aclusergroup
**, struct acluser
*, int));
96 static int AclSetPermCmd
__P((struct acluser
*, char *, struct comm
*));
97 static int AclSetPermWin
__P((struct acluser
*, struct acluser
*, char *, struct win
*));
98 static int UserAcl
__P((struct acluser
*, struct acluser
**, int, char **));
99 static int UserAclCopy
__P((struct acluser
**, struct acluser
**));
103 GrowBitfield(bfp
, len
, delta
, defaultbit
)
105 int len
, delta
, defaultbit
;
110 if (!(n
= (AclBits
)calloc(1, (unsigned long)(&ACLBYTE((char *)0, len
+ delta
+ 1)))))
112 for (i
= 0; i
< (len
+ delta
); i
++)
114 if (((i
< len
) && (ACLBIT(i
) & ACLBYTE(o
, i
))) ||
115 ((i
>= len
) && (defaultbit
)))
116 ACLBYTE(n
, i
) |= ACLBIT(i
);
124 #endif /* MULTIUSER */
127 * Returns an nonzero Address. Its contents is either a User-ptr,
128 * or NULL which may be replaced by a User-ptr to create the entry.
136 for (u
= &users
; *u
; u
= &(*u
)->u_next
)
137 if (!strcmp((*u
)->u_name
, name
))
140 debug3("FindUserPtr %s %sfound, id %d\n", name
, (*u
)?"":"not ",
142 #else /* MULTIUSER */
143 debug2("FindUserPtr %s %sfound\n", name
, (*u
)?"":"not ");
144 #endif /* MULTIUSER */
148 int DefaultEsc
= -1; /* initialised by screen.c:main() */
149 int DefaultMetaEsc
= -1;
152 * Add a new user. His password may be NULL or "" if none. His name must not
153 * be "none", as this represents the NULL-pointer when dealing with groups.
154 * He has default rights, determined by umask.
157 UserAdd(name
, pass
, up
)
166 up
= FindUserPtr(name
);
170 (*up
)->u_password
= SaveStr(pass
);
171 return 1; /* he is already there */
173 if (strcmp("none", name
)) /* "none" is a reserved word */
174 *up
= (struct acluser
*)calloc(1, sizeof(struct acluser
));
176 return -1; /* he still does not exist */
178 (*up
)->u_plop
.buf
= NULL
;
179 (*up
)->u_plop
.len
= 0;
181 (*up
)->u_plop
.enc
= 0;
184 (*up
)->u_Esc
= DefaultEsc
;
185 (*up
)->u_MetaEsc
= DefaultMetaEsc
;
186 strncpy((*up
)->u_name
, name
, 20);
187 (*up
)->u_password
= NULL
;
189 (*up
)->u_password
= SaveStr(pass
);
190 if (!(*up
)->u_password
)
191 (*up
)->u_password
= NullStr
;
192 (*up
)->u_detachwin
= -1;
193 (*up
)->u_detachotherwin
= -1;
196 (*up
)->u_group
= NULL
;
197 /* now find an unused index */
198 for ((*up
)->u_id
= 0; (*up
)->u_id
< maxusercount
; (*up
)->u_id
++)
199 if (!(ACLBIT((*up
)->u_id
) & ACLBYTE(userbits
, (*up
)->u_id
)))
201 debug2("UserAdd %s id %d\n", name
, (*up
)->u_id
);
202 if ((*up
)->u_id
== maxusercount
)
208 debug2("growing all bitfields %d += %d\n", maxusercount
, USER_CHUNK
);
209 /* the bitfields are full, grow a chunk */
210 /* first, the used_uid_indicator: */
211 if (GrowBitfield(&userbits
, maxusercount
, USER_CHUNK
, 0))
213 free((char *)*up
); *up
= NULL
; return -1;
215 /* second, default command bits */
216 /* (only if we generate commands dynamically) */
218 for (j = 0; j < ACL_BITS_PER_CMD; j++)
219 if (GrowBitfield(&default_c_userbits[j], maxusercount, USER_CHUNK,
222 free((char *)*up); *up = NULL; return -1;
225 /* third, the bits for each commands */
226 for (j
= 0; j
<= RC_LAST
; j
++)
230 for (i
= 0; i
< ACL_BITS_PER_CMD
; i
++)
231 if (GrowBitfield(&comms
[j
].userbits
[i
], maxusercount
, USER_CHUNK
,
234 free((char *)*up
); *up
= NULL
; return -1;
237 /* fourth, default window creation bits per user */
238 for (u
= users
; u
!= *up
; u
= u
->u_next
)
240 for (j
= 0; j
< ACL_BITS_PER_WIN
; j
++)
242 if (GrowBitfield(&u
->u_umask_w_bits
[j
], maxusercount
, USER_CHUNK
,
245 free((char *)*up
); *up
= NULL
; return -1;
250 /* fifth, the bits for each window */
251 /* keep these in sync with NewWindowAcl() */
252 for (w
= windows
; w
; w
= w
->w_next
)
254 /* five a: the access control list */
255 for (j
= 0; j
< ACL_BITS_PER_WIN
; j
++)
256 if (GrowBitfield(&w
->w_userbits
[j
], maxusercount
, USER_CHUNK
,
259 free((char *)*up
); *up
= NULL
; return -1;
261 /* five b: the activity notify list */
262 /* five c: the silence notify list */
263 if (GrowBitfield(&w
->w_mon_notify
, maxusercount
, USER_CHUNK
, 0) ||
264 GrowBitfield(&w
->w_lio_notify
, maxusercount
, USER_CHUNK
, 0))
266 free((char *)*up
); *up
= NULL
; return -1;
269 maxusercount
+= USER_CHUNK
;
272 /* mark the user-entry as "in-use" */
273 ACLBYTE(userbits
, (*up
)->u_id
) |= ACLBIT((*up
)->u_id
);
275 /* user id 0 is the session creator, he has all rights */
276 if ((*up
)->u_id
== 0)
277 AclSetPerm(NULL
, *up
, "+a", "#?");
279 /* user nobody has a fixed set of rights: */
280 if (!strcmp((*up
)->u_name
, "nobody"))
282 AclSetPerm(NULL
, *up
, "-rwx", "#?");
283 AclSetPerm(NULL
, *up
, "+x", "su");
284 AclSetPerm(NULL
, *up
, "+x", "detach");
285 AclSetPerm(NULL
, *up
, "+x", "displays");
286 AclSetPerm(NULL
, *up
, "+x", "version");
291 * Give default_w_bit's for all users,
292 * but allow himself everything on "his" windows.
294 for (j
= 0; j
< ACL_BITS_PER_WIN
; j
++)
296 if (GrowBitfield(&(*up
)->u_umask_w_bits
[j
], 0, maxusercount
,
299 free((char *)*up
); *up
= NULL
; return -1;
301 ACLBYTE((*up
)->u_umask_w_bits
[j
], (*up
)->u_id
) |= ACLBIT((*up
)->u_id
);
303 #else /* MULTIUSER */
304 debug1("UserAdd %s\n", name
);
305 #endif /* MULTIUSER */
310 /* change user's password */
312 UserSetPass(name
, pass
, up
)
317 up
= FindUserPtr(name
);
319 return UserAdd(name
, pass
, up
);
320 if (!strcmp(name
, "nobody")) /* he remains without password */
322 strncpy((*up
)->u_password
, pass
? pass
: "", 20);
323 (*up
)->u_password
[20] = '\0';
329 * Remove a user from the list.
330 * Destroy all his permissions and completely detach him from the session.
341 struct display
*old
, *next
;
344 up
= FindUserPtr(name
);
346 return -1; /* he who does not exist cannot be removed */
348 for (display
= displays
; display
; display
= next
)
350 next
= display
->d_next
; /* read the next ptr now, Detach may zap it. */
361 for (up
= &users
; *up
; up
= &(*up
)->u_next
)
363 /* unlink all group references to this user */
364 struct aclusergroup
**g
= &(*up
)->u_group
;
370 struct aclusergroup
*next
= (*g
)->next
;
379 ACLBYTE(userbits
, u
->u_id
) &= ~ACLBIT(u
->u_id
);
380 /* restore the bits in his slot to default: */
381 AclSetPerm(NULL
, u
, default_w_bit
[ACL_READ
] ? "+r" : "-r", "#");
382 AclSetPerm(NULL
, u
, default_w_bit
[ACL_WRITE
]? "+w" : "-w", "#");
383 AclSetPerm(NULL
, u
, default_w_bit
[ACL_EXEC
] ? "+x" : "-x", "#");
384 AclSetPerm(NULL
, u
, default_c_bit
[ACL_EXEC
] ? "+x" : "-x", "?");
385 for (i
= 0; i
< ACL_BITS_PER_WIN
; i
++)
386 free((char *)u
->u_umask_w_bits
[i
]);
387 #endif /* MULTIUSER */
388 debug1("FREEING user structure for %s\n", u
->u_name
);
390 UserFreeCopyBuffer(u
);
398 debug("Last user deleted. Feierabend.\n");
399 Finit(0); /* Destroying whole session. Noone could ever attach again. */
408 * returns 0 if the copy buffer was really deleted.
409 * Also removes any references into the users copybuffer
412 UserFreeCopyBuffer(u
)
420 for (w
= windows
; w
; w
= w
->w_next
)
423 if (pa
->pa_pasteptr
>= u
->u_plop
.buf
&&
424 pa
->pa_pasteptr
- u
->u_plop
.buf
< u
->u_plop
.len
)
427 free((char *)u
->u_plop
.buf
);
432 #endif /* COPY_PASTE */
436 * Traverses group nodes. It searches for a node that references user u.
437 * If recursive is true, nodes found in the users are also searched using
438 * depth first method. If none of the nodes references u, the address of
439 * the last next pointer is returned. This address will contain NULL.
441 static struct aclusergroup
**
442 FindGroupPtr(gp
, u
, recursive
)
443 struct aclusergroup
**gp
;
447 struct aclusergroup
**g
;
449 ASSERT(recursive
< 1000); /* Ouch, cycle detection failed */
453 return gp
; /* found him here. */
455 *(g
= FindGroupPtr(&(*gp
)->u
->u_group
, u
, recursive
+ 1)))
456 return g
; /* found him there. */
459 return gp
; /* *gp is NULL */
463 * Returns nonzero if failed or already linked.
464 * Both users are created on demand.
465 * Cyclic links are prevented.
468 AclLinkUser(from
, to
)
471 struct acluser
**u1
, **u2
;
472 struct aclusergroup
**g
;
474 if (!*(u1
= FindUserPtr(from
)) && UserAdd(from
, NULL
, u1
))
476 if (!*(u2
= FindUserPtr(to
)) && UserAdd(to
, NULL
, u2
))
477 return -1; /* hmm, could not find both users. */
479 if (*FindGroupPtr(&(*u2
)->u_group
, *u1
, 1))
480 return 1; /* cyclic link detected! */
481 if (*(g
= FindGroupPtr(&(*u1
)->u_group
, *u2
, 0)))
482 return 2; /* aha, we are already linked! */
484 if (!(*g
= (struct aclusergroup
*)malloc(sizeof(struct aclusergroup
))))
485 return -1; /* Could not alloc link. Poor screen */
492 * The user pointer stored at *up will be substituted by a pointer
493 * to the named user's structure, if passwords match.
494 * returns NULL if successfull, an static error string otherwise
497 DoSu(up
, name
, pw1
, pw2
)
499 char *name
, *pw1
, *pw2
;
504 if (!(u
= *FindUserPtr(name
)))
516 if (!(pp
= getpwnam(name
)))
518 debug1("getpwnam(\"%s\") failed\n", name
);
519 if (!(pw1
&& *pw1
&& *pw1
!= '\377'))
521 debug("no unix account, no screen passwd\n");
526 pass
= pp
->pw_passwd
;
528 for (t
= 0; t
< 13; t
++)
531 if (!(c
== '.' || c
== '/' ||
532 (c
>= '0' && c
<= '9') ||
533 (c
>= 'a' && c
<= 'z') ||
534 (c
>= 'A' && c
<= 'Z')))
539 if (!(ss
= getspnam(name
)))
541 debug1("getspnam(\"%s\") failed\n", name
);
547 #endif /* SHADOWPW */
549 if (pw2
&& *pw2
&& *pw2
!= '\377') /* provided a system password */
551 if (!*pass
|| /* but needed none */
552 strcmp(crypt(pw2
, pass
), pass
))
554 debug("System password mismatch\n");
558 else /* no pasword provided */
559 if (*pass
) /* but need one */
562 if (pw1
&& *pw1
&& *pw1
!= '\377') /* provided a screen password */
564 if (!*u
->u_password
|| /* but needed none */
565 strcmp(crypt(pw1
, u
->u_password
), u
->u_password
))
567 debug("screen password mismatch\n");
571 else /* no pasword provided */
572 if (*u
->u_password
) /* but need one */
576 debug2("syslog(LOG_NOTICE, \"screen %s: \"su %s\" ", SockPath
, name
);
577 debug2("%s for \"%s\"\n", sorry
? "failed" : "succeded", (*up
)->u_name
);
580 openlog("screen", LOG_PID
);
582 openlog("screen", LOG_PID
, LOG_AUTH
);
584 syslog(LOG_NOTICE
, "%s: \"su %s\" %s for \"%s\"", SockPath
, name
,
585 sorry
? "failed" : "succeded", (*up
)->u_name
);
588 debug("NOT LOGGED.\n");
589 #endif /* NOSYSLOG */
594 *up
= u
; /* substitute user now */
597 #endif /* MULTIUSER */
599 /************************************************************************
600 * end of user managing code *
601 ************************************************************************/
606 /* This gives the users default rights to the new window w created by u */
614 debug2("NewWindowAcl %s's umask_w_bits for window %d\n",
615 u
? u
->u_name
: "everybody", w
->w_number
);
617 /* keep these in sync with UserAdd part five. */
618 if (GrowBitfield(&w
->w_mon_notify
, 0, maxusercount
, 0) ||
619 GrowBitfield(&w
->w_lio_notify
, 0, maxusercount
, 0))
621 for (j
= 0; j
< ACL_BITS_PER_WIN
; j
++)
623 /* we start with len 0 for the new bitfield size and add maxusercount */
624 if (GrowBitfield(&w
->w_userbits
[j
], 0, maxusercount
, 0))
627 free((char *)w
->w_userbits
[j
]);
628 free((char *)w
->w_mon_notify
);
629 free((char *)w
->w_lio_notify
);
632 for (i
= 0; i
< maxusercount
; i
++)
633 if (u
? (ACLBIT(i
) & ACLBYTE(u
->u_umask_w_bits
[j
], i
)) :
635 ACLBYTE(w
->w_userbits
[j
], i
) |= ACLBIT(i
);
646 for (i
= 0; i
< ACL_BITS_PER_WIN
; i
++)
647 free((char *)w
->w_userbits
[i
]);
648 free((char *)w
->w_mon_notify
);
649 free((char *)w
->w_lio_notify
);
653 /* if mode starts with '-' we remove the users exec bit for cmd */
655 * NOTE: before you make this function look the same as
656 * AclSetPermWin, try to merge both functions.
659 AclSetPermCmd(u
, mode
, cmd
)
680 /* debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name); */
682 ACLBYTE(cmd
->userbits
[ACL_EXEC
], u
->u_id
) &= ~ACLBIT(u
->u_id
);
684 ACLBYTE(cmd
->userbits
[ACL_EXEC
], u
->u_id
) |= ACLBIT(u
->u_id
);
696 /* mode strings of the form +rwx -w+rx r -wx are parsed and evaluated */
699 * releases a writelock on window 2 held by user nerd.
700 * Letter n allows network access on a window.
701 * uu should be NULL, except if you want to change his umask.
704 AclSetPermWin(uu
, u
, mode
, win
)
705 struct acluser
*u
, *uu
;
716 debug3("AclSetPermWin %s UMASK %s %s\n", uu
->u_name
, u
->u_name
, mode
);
717 bitarray
= uu
->u_umask_w_bits
;
722 bitarray
= win
->w_userbits
;
723 debug3("AclSetPermWin %s %s %d\n", u
->u_name
, mode
, win
->w_number
);
737 bits
= (1 << ACL_READ
);
740 bits
= (1 << ACL_WRITE
);
743 bits
= (1 << ACL_EXEC
);
746 bits
= (1 << ACL_BITS_PER_WIN
) - 1;
751 for (bit
= 0; bit
< ACL_BITS_PER_WIN
; bit
++)
753 if (!(bits
& (1 << bit
)))
756 ACLBYTE(bitarray
[bit
], u
->u_id
) &= ~ACLBIT(u
->u_id
);
758 ACLBYTE(bitarray
[bit
], u
->u_id
) |= ACLBIT(u
->u_id
);
759 if (!uu
&& (win
->w_wlockuser
== u
) && neg
&& (bit
== ACL_WRITE
))
761 debug2("%s lost writelock on win %d\n", u
->u_name
, win
->w_number
);
762 win
->w_wlockuser
= NULL
;
763 if (win
->w_wlock
== WLOCK_ON
)
764 win
->w_wlock
= WLOCK_AUTO
;
768 if (uu
&& u
->u_name
[0] == '?' && u
->u_name
[1] == '\0')
771 * It is Mr. '?', the unknown user. He deserves special treatment as
772 * he defines the defaults. Sorry, this is global, not per user.
776 debug1("AclSetPermWin: default_w_bits '%s'.\n", mode
);
777 for (bit
= 0; bit
< ACL_BITS_PER_WIN
; bit
++)
779 (ACLBYTE(bitarray
[bit
], u
->u_id
) & ACLBIT(u
->u_id
)) ? 1 : 0;
784 * Hack. I do not want to duplicate all the above code for
785 * AclSetPermCmd. This asumes that there are not more bits
786 * per cmd than per win.
788 debug1("AclSetPermWin: default_c_bits '%s'.\n", mode
);
789 for (bit
= 0; bit
< ACL_BITS_PER_CMD
; bit
++)
791 (ACLBYTE(bitarray
[bit
], u
->u_id
) & ACLBIT(u
->u_id
)) ? 1 : 0;
793 UserDel(u
->u_name
, NULL
);
799 * String is broken down into comand and window names, mode applies
800 * A command name matches first, so do not use these as window names.
801 * uu should be NULL, except if you want to change his umask.
804 AclSetPerm(uu
, u
, mode
, s
)
805 struct acluser
*uu
, *u
;
812 debug3("AclSetPerm(uu, user '%s', mode '%s', object '%s')\n",
818 case '*': /* all windows and all commands */
819 return AclSetPerm(uu
, u
, mode
, "#?");
821 if (uu
) /* window umask or .. */
822 AclSetPermWin(uu
, u
, mode
, (struct win
*)1);
823 else /* .. or all windows */
824 for (w
= windows
; w
; w
= w
->w_next
)
825 AclSetPermWin((struct acluser
*)0, u
, mode
, w
);
829 if (uu
) /* command umask or .. */
830 AclSetPermWin(uu
, u
, mode
, (struct win
*)0);
831 else /* .. or all commands */
832 for (i
= 0; i
<= RC_LAST
; i
++)
833 AclSetPermCmd(u
, mode
, &comms
[i
]);
837 for (p
= s
; *p
&& *p
!= ' ' && *p
!= '\t' && *p
!= ','; p
++)
841 if ((i
= FindCommnr(s
)) != RC_ILLEGAL
)
842 AclSetPermCmd(u
, mode
, &comms
[i
]);
843 else if (((i
= WindowByNoN(s
)) >= 0) && wtab
[i
])
844 AclSetPermWin((struct acluser
*)0, u
, mode
, wtab
[i
]);
846 /* checking group name */
857 * Generic ACL Manager:
859 * This handles acladd and aclchg identical.
860 * With 2 or 4 parameters, the second parameter is a password.
861 * With 3 or 4 parameters the last two parameters specify the permissions
862 * else user is added with full permissions.
863 * With 1 parameter the users permissions are copied from user *argv.
864 * Unlike the other cases, u->u_name should not match *argv here.
865 * uu should be NULL, except if you want to change his umask.
868 UserAcl(uu
, u
, argc
, argv
)
869 struct acluser
*uu
, **u
;
873 if ((*u
&& !strcmp((*u
)->u_name
, "nobody")) ||
874 (argc
> 1 && !strcmp(argv
[0], "nobody")))
875 return -1; /* do not change nobody! */
880 debug2("UserAcl: user '%s', password '%s':", argv
[0], argv
[1]);
881 return (UserAdd(argv
[0], argv
[1], u
) < 0) ||
882 AclSetPerm(uu
, *u
, argv
[2], argv
[3]);
884 debug1("UserAcl: user '%s', no password:", argv
[0]);
885 return (UserAdd(argv
[0], NULL
, u
) < 0) ||
886 AclSetPerm(uu
, *u
, argv
[1], argv
[2]);
888 debug2("UserAcl: user '%s', password '%s'\n", argv
[0], argv
[1]);
889 return UserAdd(argv
[0], argv
[1], u
) < 0;
891 debug1("UserAcl: user '%s', no password:", argv
[0]);
892 return (UserAdd(argv
[0], NULL
, u
) < 0) ||
893 AclSetPerm(uu
, *u
, "+a", "#?");
900 UserAclCopy(to_up
, from_up
)
901 struct acluser
**to_up
, **from_up
;
904 int i
, j
, to_id
, from_id
;
906 if (!*to_up
|| !*from_up
)
908 debug2("UserAclCopy: from user '%s' to user '%s'\n",
909 (*from_up
)->u_name
, (*to_up
)->u_name
);
910 if ((to_id
= (*to_up
)->u_id
) == (from_id
= (*from_up
)->u_id
))
912 for (w
= windows
; w
; w
= w
->w_next
)
914 for (i
= 0; i
< ACL_BITS_PER_WIN
; i
++)
916 if (ACLBYTE(w
->w_userbits
[i
], from_id
) & ACLBIT(from_id
))
917 ACLBYTE(w
->w_userbits
[i
], to_id
) |= ACLBIT(to_id
);
920 ACLBYTE(w
->w_userbits
[i
], to_id
) &= ~ACLBIT(to_id
);
921 if ((w
->w_wlockuser
== *to_up
) && (i
== ACL_WRITE
))
923 debug2("%s lost wlock on win %d\n",
924 (*to_up
)->u_name
, w
->w_number
);
925 w
->w_wlockuser
= NULL
;
926 if (w
->w_wlock
== WLOCK_ON
)
927 w
->w_wlock
= WLOCK_AUTO
;
932 for (j
= 0; j
<= RC_LAST
; j
++)
934 for (i
= 0; i
< ACL_BITS_PER_CMD
; i
++)
936 if (ACLBYTE(comms
[j
].userbits
[i
], from_id
) & ACLBIT(from_id
))
937 ACLBYTE(comms
[j
].userbits
[i
], to_id
) |= ACLBIT(to_id
);
939 ACLBYTE(comms
[j
].userbits
[i
], to_id
) &= ~ACLBIT(to_id
);
948 * user [password] [+rwx #?]
949 * * [password] [+rwx #?]
950 * user1,user2,user3 [password] [+rwx #?]
951 * user1,user2,user3=user
952 * uu should be NULL, except if you want to change his umask.
955 UsersAcl(uu
, argc
, argv
)
962 struct acluser
**cf_u
= NULL
;
970 if (*s
++ == '=') p
= s
;
974 cf_u
= FindUserPtr(p
);
978 if (argv
[0][0] == '*' && argv
[0][1] == '\0')
982 debug("all users acls.\n");
983 for (u
= &users
; *u
; u
= &(*u
)->u_next
)
984 if (strcmp("nobody", (*u
)->u_name
) &&
986 ((r
= UserAclCopy(u
, cf_u
)) < 0) :
987 ((r
= UserAcl(uu
, u
, argc
, argv
)) < 0)))
994 for (s
= argv
[0]; *s
&& *s
!=' ' && *s
!='\t' && *s
!=',' && *s
!='='; s
++)
996 *s
? (*s
++ = '\0') : (*s
= '\0');
997 debug2("UsersAcl(uu, \"%s\", argc=%d)\n", argv
[0], argc
);
999 ((r
= UserAclCopy(FindUserPtr(argv
[0]), cf_u
)) < 0) :
1000 ((r
= UserAcl(uu
, FindUserPtr(argv
[0]), argc
, argv
)) < 0))
1002 } while (*(argv
[0] = s
));
1007 * Preprocess argments, so that umask can be set with UsersAcl
1009 * all current users umask ±rwxn
1010 * one specific user umask user1±rwxn
1011 * several users umask user1,user2,...±rwxn
1012 * default_w_bits umask ?±rwxn
1013 * default_c_bits umask ??±rwxn
1016 AclUmask(u
, str
, errp
)
1025 /* split str into user and bits section. */
1026 for (p
= str
; *p
; p
++)
1027 if ((c
= *p
) == '+' || c
== '-')
1031 *errp
= "Bad argument. Should be ``[user[,user...]{+|-}rwxn''.";
1034 strncpy(mode
, p
, 15);
1038 /* construct argument vector */
1039 if (!strcmp("??", str
))
1047 av
[0] = *str
? str
: "*";
1049 if (UsersAcl(u
, 3, av
))
1051 *errp
= "UsersAcl failed. Hmmm.";
1063 debug2("AclWinSwap(%d, %d) NOP.\n", a
, b
);
1066 struct acluser
*EffectiveAclUser
= NULL
; /* hook for AT command permission */
1069 AclCheckPermWin(u
, mode
, w
)
1076 if (mode
< 0 || mode
>= ACL_BITS_PER_WIN
)
1078 if (EffectiveAclUser
)
1080 debug1("AclCheckPermWin: WARNING user %s overridden!\n", u
->u_name
);
1081 u
= EffectiveAclUser
;
1083 ok
= ACLBYTE(w
->w_userbits
[mode
], u
->u_id
) & ACLBIT(u
->u_id
);
1084 debug3("AclCheckPermWin(%s, %d, %d) = ", u
->u_name
, mode
, w
->w_number
);
1088 struct aclusergroup
**g
= &u
->u_group
;
1089 struct acluser
*saved_eff
= EffectiveAclUser
;
1091 EffectiveAclUser
= NULL
;
1094 if (!AclCheckPermWin((*g
)->u
, mode
, w
))
1098 EffectiveAclUser
= saved_eff
;
1102 debug1("%d\n", !ok
);
1107 AclCheckPermCmd(u
, mode
, c
)
1114 if (mode
< 0 || mode
>= ACL_BITS_PER_CMD
)
1116 if (EffectiveAclUser
)
1118 debug1("AclCheckPermCmd: WARNING user %s overridden!\n", u
->u_name
);
1119 u
= EffectiveAclUser
;
1121 ok
= ACLBYTE(c
->userbits
[mode
], u
->u_id
) & ACLBIT(u
->u_id
);
1122 debug3("AclCheckPermCmd(%s %d %s) = ", u
->u_name
, mode
, c
->name
);
1125 struct aclusergroup
**g
= &u
->u_group
;
1126 struct acluser
*saved_eff
= EffectiveAclUser
;
1128 EffectiveAclUser
= NULL
;
1131 if (!AclCheckPermCmd((*g
)->u
, mode
, c
))
1135 EffectiveAclUser
= saved_eff
;
1139 debug1("%d\n", !ok
);
1143 #endif /* MULTIUSER */