1/* Copyright (c) 1993-2002 2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) 3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) 4 * Copyright (c) 1987 Oliver Laumann 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2, or (at your option) 9 * any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program (see the file COPYING); if not, write to the 18 * Free Software Foundation, Inc., 19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 20 * 21 **************************************************************** 22 */ 23 24#include <sys/types.h> 25 26#include "config.h" 27 28 29/* XXX: WHY IS THIS HERE?? :XXX */ 30 31#ifdef CHECKLOGIN 32# ifdef _SEQUENT_ 33# include <stdio.h> /* needed by <pwd.h> */ 34# endif /* _SEQUENT_ */ 35# include <pwd.h> 36# ifdef SHADOWPW 37# include <shadow.h> 38# endif /* SHADOWPW */ 39#endif /* CHECKLOGIN */ 40 41#ifndef NOSYSLOG 42# include <syslog.h> 43#endif 44 45#include "screen.h" /* includes acls.h */ 46#include "extern.h" 47 48 49/************************************************************************ 50 * user managing code, this does not really belong into the acl stuff * 51 ************************************************************************/ 52 53extern struct comm comms[]; 54extern struct win *windows, *wtab[]; 55extern char NullStr[]; 56extern char SockPath[]; 57extern struct display *display, *displays; 58struct acluser *users; 59 60#ifdef MULTIUSER 61int maxusercount = 0; /* used in process.c: RC_MONITOR, RC_SILENCE */ 62 63/* record given user ids here */ 64static AclBits userbits; 65 66/* 67 * rights a new unknown user will have on windows and cmds. 68 * These are changed by a "umask ?-..." command: 69 */ 70static char default_w_bit[ACL_BITS_PER_WIN] = 71{ 72 1, /* EXEC */ 73 1, /* WRITE */ 74 1 /* READ */ 75}; 76 77static char default_c_bit[ACL_BITS_PER_CMD] = 78{ 79 0 /* EXEC */ 80}; 81 82/* rights of all users per newly created window */ 83/* 84 * are now stored per user (umask) 85 * static AclBits default_w_userbits[ACL_BITS_PER_WIN]; 86 * static AclBits default_c_userbits[ACL_BITS_PER_CMD]; 87 */ 88 89static int GrowBitfield __P((AclBits *, int, int, int)); 90static struct aclusergroup **FindGroupPtr __P((struct aclusergroup **, struct acluser *, int)); 91static int AclSetPermCmd __P((struct acluser *, char *, struct comm *)); 92static int AclSetPermWin __P((struct acluser *, struct acluser *, char *, struct win *)); 93static int UserAcl __P((struct acluser *, struct acluser **, int, char **)); 94static int UserAclCopy __P((struct acluser **, struct acluser **)); 95 96 97static int 98GrowBitfield(bfp, len, delta, defaultbit) 99AclBits *bfp; 100int len, delta, defaultbit; 101{ 102 AclBits n, o = *bfp; 103 int i; 104 105 if (!(n = (AclBits)calloc(1, (unsigned long)(&ACLBYTE((char *)0, len + delta + 1))))) 106 return -1; 107 for (i = 0; i < (len + delta); i++) 108 { 109 if (((i < len) && (ACLBIT(i) & ACLBYTE(o, i))) || 110 ((i >= len) && (defaultbit))) 111 ACLBYTE(n, i) |= ACLBIT(i); 112 } 113 if (len) 114 free((char *)o); 115 *bfp = n; 116 return 0; 117} 118 119#endif /* MULTIUSER */ 120 121/* 122 * Returns an nonzero Address. Its contents is either a User-ptr, 123 * or NULL which may be replaced by a User-ptr to create the entry. 124 */ 125struct acluser ** 126FindUserPtr(name) 127char *name; 128{ 129 struct acluser **u; 130 131 for (u = &users; *u; u = &(*u)->u_next) 132 if (!strcmp((*u)->u_name, name)) 133 break; 134#ifdef MULTIUSER 135 debug3("FindUserPtr %s %sfound, id %d\n", name, (*u)?"":"not ", 136 (*u)?(*u)->u_id:-1); 137#else /* MULTIUSER */ 138 debug2("FindUserPtr %s %sfound\n", name, (*u)?"":"not "); 139#endif /* MULTIUSER */ 140 return u; 141} 142 143int DefaultEsc = -1; /* initialised by screen.c:main() */ 144int DefaultMetaEsc = -1; 145 146/* 147 * Add a new user. His password may be NULL or "" if none. His name must not 148 * be "none", as this represents the NULL-pointer when dealing with groups. 149 * He has default rights, determined by umask. 150 */ 151int 152UserAdd(name, pass, up) 153char *name, *pass; 154struct acluser **up; 155{ 156#ifdef MULTIUSER 157 int j; 158#endif 159 160 if (!up) 161 up = FindUserPtr(name); 162 if (*up) 163 { 164 if (pass) 165 (*up)->u_password = SaveStr(pass); 166 return 1; /* he is already there */ 167 } 168 if (strcmp("none", name)) /* "none" is a reserved word */ 169 *up = (struct acluser *)calloc(1, sizeof(struct acluser)); 170 if (!*up) 171 return -1; /* he still does not exist */ 172#ifdef COPY_PASTE 173 (*up)->u_plop.buf = NULL; 174 (*up)->u_plop.len = 0; 175# ifdef ENCODINGS 176 (*up)->u_plop.enc = 0; 177# endif 178#endif 179 (*up)->u_Esc = DefaultEsc; 180 (*up)->u_MetaEsc = DefaultMetaEsc; 181 strncpy((*up)->u_name, name, 20); 182 (*up)->u_password = NULL; 183 if (pass) 184 (*up)->u_password = SaveStr(pass); 185 if (!(*up)->u_password) 186 (*up)->u_password = NullStr; 187 (*up)->u_detachwin = -1; 188 (*up)->u_detachotherwin = -1; 189 190#ifdef MULTIUSER 191 (*up)->u_group = NULL; 192 /* now find an unused index */ 193 for ((*up)->u_id = 0; (*up)->u_id < maxusercount; (*up)->u_id++) 194 if (!(ACLBIT((*up)->u_id) & ACLBYTE(userbits, (*up)->u_id))) 195 break; 196 debug2("UserAdd %s id %d\n", name, (*up)->u_id); 197 if ((*up)->u_id == maxusercount) 198 { 199 int j; 200 struct win *w; 201 struct acluser *u; 202 203 debug2("growing all bitfields %d += %d\n", maxusercount, USER_CHUNK); 204 /* the bitfields are full, grow a chunk */ 205 /* first, the used_uid_indicator: */ 206 if (GrowBitfield(&userbits, maxusercount, USER_CHUNK, 0)) 207 { 208 free((char *)*up); *up = NULL; return -1; 209 } 210 /* second, default command bits */ 211 /* (only if we generate commands dynamically) */ 212/* 213 for (j = 0; j < ACL_BITS_PER_CMD; j++) 214 if (GrowBitfield(&default_c_userbits[j], maxusercount, USER_CHUNK, 215 default_c_bit[j])) 216 { 217 free((char *)*up); *up = NULL; return -1; 218 } 219*/ 220 /* third, the bits for each commands */ 221 for (j = 0; j <= RC_LAST; j++) 222 { 223 int i; 224 225 for (i = 0; i < ACL_BITS_PER_CMD; i++) 226 if (GrowBitfield(&comms[j].userbits[i], maxusercount, USER_CHUNK, 227 default_c_bit[i])) 228 { 229 free((char *)*up); *up = NULL; return -1; 230 } 231 } 232 /* fourth, default window creation bits per user */ 233 for (u = users; u != *up; u = u->u_next) 234 { 235 for (j = 0; j < ACL_BITS_PER_WIN; j++) 236 { 237 if (GrowBitfield(&u->u_umask_w_bits[j], maxusercount, USER_CHUNK, 238 default_w_bit[j])) 239 { 240 free((char *)*up); *up = NULL; return -1; 241 } 242 } 243 } 244 245 /* fifth, the bits for each window */ 246 /* keep these in sync with NewWindowAcl() */ 247 for (w = windows; w; w = w->w_next) 248 { 249 /* five a: the access control list */ 250 for (j = 0; j < ACL_BITS_PER_WIN; j++) 251 if (GrowBitfield(&w->w_userbits[j], maxusercount, USER_CHUNK, 252 default_w_bit[j])) 253 { 254 free((char *)*up); *up = NULL; return -1; 255 } 256 /* five b: the activity notify list */ 257 /* five c: the silence notify list */ 258 if (GrowBitfield(&w->w_mon_notify, maxusercount, USER_CHUNK, 0) || 259 GrowBitfield(&w->w_lio_notify, maxusercount, USER_CHUNK, 0)) 260 { 261 free((char *)*up); *up = NULL; return -1; 262 } 263 } 264 maxusercount += USER_CHUNK; 265 } 266 267 /* mark the user-entry as "in-use" */ 268 ACLBYTE(userbits, (*up)->u_id) |= ACLBIT((*up)->u_id); 269 270 /* user id 0 is the session creator, he has all rights */ 271 if ((*up)->u_id == 0) 272 AclSetPerm(NULL, *up, "+a", "#?"); 273 274 /* user nobody has a fixed set of rights: */ 275 if (!strcmp((*up)->u_name, "nobody")) 276 { 277 AclSetPerm(NULL, *up, "-rwx", "#?"); 278 AclSetPerm(NULL, *up, "+x", "su"); 279 AclSetPerm(NULL, *up, "+x", "detach"); 280 AclSetPerm(NULL, *up, "+x", "displays"); 281 AclSetPerm(NULL, *up, "+x", "version"); 282 } 283 284 /* 285 * Create his umask: 286 * Give default_w_bit's for all users, 287 * but allow himself everything on "his" windows. 288 */ 289 for (j = 0; j < ACL_BITS_PER_WIN; j++) 290 { 291 if (GrowBitfield(&(*up)->u_umask_w_bits[j], 0, maxusercount, 292 default_w_bit[j])) 293 { 294 free((char *)*up); *up = NULL; return -1; 295 } 296 ACLBYTE((*up)->u_umask_w_bits[j], (*up)->u_id) |= ACLBIT((*up)->u_id); 297 } 298#else /* MULTIUSER */ 299 debug1("UserAdd %s\n", name); 300#endif /* MULTIUSER */ 301 return 0; 302} 303 304#if 0 305/* change user's password */ 306int 307UserSetPass(name, pass, up) 308char *name, *pass; 309struct acluser **up; 310{ 311 if (!up) 312 up = FindUserPtr(name); 313 if (!*up) 314 return UserAdd(name, pass, up); 315 if (!strcmp(name, "nobody")) /* he remains without password */ 316 return -1; 317 strncpy((*up)->u_password, pass ? pass : "", 20); 318 (*up)->u_password[20] = '\0'; 319 return 0; 320} 321#endif 322 323/* 324 * Remove a user from the list. 325 * Destroy all his permissions and completely detach him from the session. 326 */ 327int 328UserDel(name, up) 329char *name; 330struct acluser **up; 331{ 332 struct acluser *u; 333#ifdef MULTIUSER 334 int i; 335#endif 336 struct display *old, *next; 337 338 if (!up) 339 up = FindUserPtr(name); 340 if (!(u = *up)) 341 return -1; /* he who does not exist cannot be removed */ 342 old = display; 343 for (display = displays; display; display = next) 344 { 345 next = display->d_next; /* read the next ptr now, Detach may zap it. */ 346 if (D_user != u) 347 continue; 348 if (display == old) 349 old = NULL; 350 Detach(D_REMOTE); 351 } 352 display = old; 353 *up = u->u_next; 354 355#ifdef MULTIUSER 356 for (up = &users; *up; up = &(*up)->u_next) 357 { 358 /* unlink all group references to this user */ 359 struct aclusergroup **g = &(*up)->u_group; 360 361 while (*g) 362 { 363 if ((*g)->u == u) 364 { 365 struct aclusergroup *next = (*g)->next; 366 367 free((char *)(*g)); 368 *g = next; 369 } 370 else 371 g = &(*g)->next; 372 } 373 } 374 ACLBYTE(userbits, u->u_id) &= ~ACLBIT(u->u_id); 375 /* restore the bits in his slot to default: */ 376 AclSetPerm(NULL, u, default_w_bit[ACL_READ] ? "+r" : "-r", "#"); 377 AclSetPerm(NULL, u, default_w_bit[ACL_WRITE]? "+w" : "-w", "#"); 378 AclSetPerm(NULL, u, default_w_bit[ACL_EXEC] ? "+x" : "-x", "#"); 379 AclSetPerm(NULL, u, default_c_bit[ACL_EXEC] ? "+x" : "-x", "?"); 380 for (i = 0; i < ACL_BITS_PER_WIN; i++) 381 free((char *)u->u_umask_w_bits[i]); 382#endif /* MULTIUSER */ 383 debug1("FREEING user structure for %s\n", u->u_name); 384#ifdef COPY_PASTE 385 UserFreeCopyBuffer(u); 386#endif 387 free((char *)u); 388 if (!users) 389 { 390 debug("Last user deleted. Feierabend.\n"); 391 Finit(0); /* Destroying whole session. Noone could ever attach again. */ 392 } 393 return 0; 394} 395 396 397#ifdef COPY_PASTE 398 399/* 400 * returns 0 if the copy buffer was really deleted. 401 * Also removes any references into the users copybuffer 402 */ 403int 404UserFreeCopyBuffer(u) 405struct acluser *u; 406{ 407 struct win *w; 408 struct paster *pa; 409 410 if (!u->u_plop.buf) 411 return 1; 412 for (w = windows; w; w = w->w_next) 413 { 414 pa = &w->w_paster; 415 if (pa->pa_pasteptr >= u->u_plop.buf && 416 pa->pa_pasteptr - u->u_plop.buf < u->u_plop.len) 417 FreePaster(pa); 418 } 419 free((char *)u->u_plop.buf); 420 u->u_plop.len = 0; 421 u->u_plop.buf = 0; 422 return 0; 423} 424#endif /* COPY_PASTE */ 425 426#ifdef MULTIUSER 427/* 428 * Traverses group nodes. It searches for a node that references user u. 429 * If recursive is true, nodes found in the users are also searched using 430 * depth first method. If none of the nodes references u, the address of 431 * the last next pointer is returned. This address will contain NULL. 432 */ 433static struct aclusergroup ** 434FindGroupPtr(gp, u, recursive) 435struct aclusergroup **gp; 436struct acluser *u; 437int recursive; 438{ 439 struct aclusergroup **g; 440 441 ASSERT(recursive < 1000); /* Ouch, cycle detection failed */ 442 while (*gp) 443 { 444 if ((*gp)->u == u) 445 return gp; /* found him here. */ 446 if (recursive && 447 *(g = FindGroupPtr(&(*gp)->u->u_group, u, recursive + 1))) 448 return g; /* found him there. */ 449 gp = &(*gp)->next; 450 } 451 return gp; /* *gp is NULL */ 452} 453 454/* 455 * Returns nonzero if failed or already linked. 456 * Both users are created on demand. 457 * Cyclic links are prevented. 458 */ 459int 460AclLinkUser(from, to) 461char *from, *to; 462{ 463 struct acluser **u1, **u2; 464 struct aclusergroup **g; 465 466 if (!*(u1 = FindUserPtr(from)) && UserAdd(from, NULL, u1)) 467 return -1; 468 if (!*(u2 = FindUserPtr(to)) && UserAdd(to, NULL, u2)) 469 return -1; /* hmm, could not find both users. */ 470 471 if (*FindGroupPtr(&(*u2)->u_group, *u1, 1)) 472 return 1; /* cyclic link detected! */ 473 if (*(g = FindGroupPtr(&(*u1)->u_group, *u2, 0))) 474 return 2; /* aha, we are already linked! */ 475 476 if (!(*g = (struct aclusergroup *)malloc(sizeof(struct aclusergroup)))) 477 return -1; /* Could not alloc link. Poor screen */ 478 (*g)->u = (*u2); 479 (*g)->next = NULL; 480 return 0; 481} 482 483/* 484 * The user pointer stored at *up will be substituted by a pointer 485 * to the named user's structure, if passwords match. 486 * returns NULL if successfull, an static error string otherwise 487 */ 488char * 489DoSu(up, name, pw1, pw2) 490struct acluser **up; 491char *name, *pw1, *pw2; 492{ 493 struct acluser *u; 494 int sorry = 0; 495 496 if (!(u = *FindUserPtr(name))) 497 sorry++; 498 else 499 { 500#ifdef CHECKLOGIN 501 struct passwd *pp; 502#ifdef SHADOWPW 503 struct spwd *ss; 504 int t, c; 505#endif 506 char *pass = ""; 507 508 if (!(pp = getpwnam(name))) 509 { 510 debug1("getpwnam(\"%s\") failed\n", name); 511 if (!(pw1 && *pw1 && *pw1 != '\377')) 512 { 513 debug("no unix account, no screen passwd\n"); 514 sorry++; 515 } 516 } 517 else 518 pass = pp->pw_passwd; 519#ifdef SHADOWPW 520 for (t = 0; t < 13; t++) 521 { 522 c = pass[t]; 523 if (!(c == '.' || c == '/' || 524 (c >= '0' && c <= '9') || 525 (c >= 'a' && c <= 'z') || 526 (c >= 'A' && c <= 'Z'))) 527 break; 528 } 529 if (t < 13) 530 { 531 if (!(ss = getspnam(name))) 532 { 533 debug1("getspnam(\"%s\") failed\n", name); 534 sorry++; 535 } 536 else 537 pass = ss->sp_pwdp; 538 } 539#endif /* SHADOWPW */ 540 541 if (pw2 && *pw2 && *pw2 != '\377') /* provided a system password */ 542 { 543 if (!*pass || /* but needed none */ 544 strcmp(crypt(pw2, pass), pass)) 545 { 546 debug("System password mismatch\n"); 547 sorry++; 548 } 549 } 550 else /* no pasword provided */ 551 if (*pass) /* but need one */ 552 sorry++; 553#endif 554 if (pw1 && *pw1 && *pw1 != '\377') /* provided a screen password */ 555 { 556 if (!*u->u_password || /* but needed none */ 557 strcmp(crypt(pw1, u->u_password), u->u_password)) 558 { 559 debug("screen password mismatch\n"); 560 sorry++; 561 } 562 } 563 else /* no pasword provided */ 564 if (*u->u_password) /* but need one */ 565 sorry++; 566 } 567 568 debug2("syslog(LOG_NOTICE, \"screen %s: \"su %s\" ", SockPath, name); 569 debug2("%s for \"%s\"\n", sorry ? "failed" : "succeded", (*up)->u_name); 570#ifndef NOSYSLOG 571# ifdef BSD_42 572 openlog("screen", LOG_PID); 573# else 574 openlog("screen", LOG_PID, LOG_AUTH); 575# endif /* BSD_42 */ 576 syslog(LOG_NOTICE, "%s: \"su %s\" %s for \"%s\"", SockPath, name, 577 sorry ? "failed" : "succeded", (*up)->u_name); 578 closelog(); 579#else 580 debug("NOT LOGGED.\n"); 581#endif /* NOSYSLOG */ 582 583 if (sorry) 584 return "Sorry."; 585 else 586 *up = u; /* substitute user now */ 587 return NULL; 588} 589#endif /* MULTIUSER */ 590 591/************************************************************************ 592 * end of user managing code * 593 ************************************************************************/ 594 595 596#ifdef MULTIUSER 597 598/* This gives the users default rights to the new window w created by u */ 599int 600NewWindowAcl(w, u) 601struct win *w; 602struct acluser *u; 603{ 604 int i, j; 605 606 debug2("NewWindowAcl %s's umask_w_bits for window %d\n", 607 u ? u->u_name : "everybody", w->w_number); 608 609 /* keep these in sync with UserAdd part five. */ 610 if (GrowBitfield(&w->w_mon_notify, 0, maxusercount, 0) || 611 GrowBitfield(&w->w_lio_notify, 0, maxusercount, 0)) 612 return -1; 613 for (j = 0; j < ACL_BITS_PER_WIN; j++) 614 { 615 /* we start with len 0 for the new bitfield size and add maxusercount */ 616 if (GrowBitfield(&w->w_userbits[j], 0, maxusercount, 0)) 617 { 618 while (--j >= 0) 619 free((char *)w->w_userbits[j]); 620 free((char *)w->w_mon_notify); 621 free((char *)w->w_lio_notify); 622 return -1; 623 } 624 for (i = 0; i < maxusercount; i++) 625 if (u ? (ACLBIT(i) & ACLBYTE(u->u_umask_w_bits[j], i)) : 626 default_w_bit[j]) 627 ACLBYTE(w->w_userbits[j], i) |= ACLBIT(i); 628 } 629 return 0; 630} 631 632void 633FreeWindowAcl(w) 634struct win *w; 635{ 636 int i; 637 638 for (i = 0; i < ACL_BITS_PER_WIN; i++) 639 free((char *)w->w_userbits[i]); 640 free((char *)w->w_mon_notify); 641 free((char *)w->w_lio_notify); 642} 643 644 645/* if mode starts with '-' we remove the users exec bit for cmd */ 646/* 647 * NOTE: before you make this function look the same as 648 * AclSetPermWin, try to merge both functions. 649 */ 650static int 651AclSetPermCmd(u, mode, cmd) 652struct acluser *u; 653char *mode; 654struct comm *cmd; 655{ 656 int neg = 0; 657 char *m = mode; 658 659 while (*m) 660 { 661 switch (*m++) 662 { 663 case '-': 664 neg = 1; 665 continue; 666 case '+': 667 neg = 0; 668 continue; 669 case 'a': 670 case 'e': 671 case 'x': 672/* debug3("AclSetPermCmd %s %s %s\n", u->u_name, mode, cmd->name); */ 673 if (neg) 674 ACLBYTE(cmd->userbits[ACL_EXEC], u->u_id) &= ~ACLBIT(u->u_id); 675 else 676 ACLBYTE(cmd->userbits[ACL_EXEC], u->u_id) |= ACLBIT(u->u_id); 677 break; 678 case 'r': 679 case 'w': 680 break; 681 default: 682 return -1; 683 } 684 } 685 return 0; 686} 687 688/* mode strings of the form +rwx -w+rx r -wx are parsed and evaluated */ 689/* 690 * aclchg nerd -w+w 2 691 * releases a writelock on window 2 held by user nerd. 692 * Letter n allows network access on a window. 693 * uu should be NULL, except if you want to change his umask. 694 */ 695static int 696AclSetPermWin(uu, u, mode, win) 697struct acluser *u, *uu; 698char *mode; 699struct win *win; 700{ 701 int neg = 0; 702 int bit, bits; 703 AclBits *bitarray; 704 char *m = mode; 705 706 if (uu) 707 { 708 debug3("AclSetPermWin %s UMASK %s %s\n", uu->u_name, u->u_name, mode); 709 bitarray = uu->u_umask_w_bits; 710 } 711 else 712 { 713 ASSERT(win); 714 bitarray = win->w_userbits; 715 debug3("AclSetPermWin %s %s %d\n", u->u_name, mode, win->w_number); 716 } 717 718 while (*m) 719 { 720 switch (*m++) 721 { 722 case '-': 723 neg = 1; 724 continue; 725 case '+': 726 neg = 0; 727 continue; 728 case 'r': 729 bits = (1 << ACL_READ); 730 break; 731 case 'w': 732 bits = (1 << ACL_WRITE); 733 break; 734 case 'x': 735 bits = (1 << ACL_EXEC); 736 break; 737 case 'a': 738 bits = (1 << ACL_BITS_PER_WIN) - 1; 739 break; 740 default: 741 return -1; 742 } 743 for (bit = 0; bit < ACL_BITS_PER_WIN; bit++) 744 { 745 if (!(bits & (1 << bit))) 746 continue; 747 if (neg) 748 ACLBYTE(bitarray[bit], u->u_id) &= ~ACLBIT(u->u_id); 749 else 750 ACLBYTE(bitarray[bit], u->u_id) |= ACLBIT(u->u_id); 751 if (!uu && (win->w_wlockuser == u) && neg && (bit == ACL_WRITE)) 752 { 753 debug2("%s lost writelock on win %d\n", u->u_name, win->w_number); 754 win->w_wlockuser = NULL; 755 if (win->w_wlock == WLOCK_ON) 756 win->w_wlock = WLOCK_AUTO; 757 } 758 } 759 } 760 if (uu && u->u_name[0] == '?' && u->u_name[1] == '\0') 761 { 762 /* 763 * It is Mr. '?', the unknown user. He deserves special treatment as 764 * he defines the defaults. Sorry, this is global, not per user. 765 */ 766 if (win) 767 { 768 debug1("AclSetPermWin: default_w_bits '%s'.\n", mode); 769 for (bit = 0; bit < ACL_BITS_PER_WIN; bit++) 770 default_w_bit[bit] = 771 (ACLBYTE(bitarray[bit], u->u_id) & ACLBIT(u->u_id)) ? 1 : 0; 772 } 773 else 774 { 775 /* 776 * Hack. I do not want to duplicate all the above code for 777 * AclSetPermCmd. This asumes that there are not more bits 778 * per cmd than per win. 779 */ 780 debug1("AclSetPermWin: default_c_bits '%s'.\n", mode); 781 for (bit = 0; bit < ACL_BITS_PER_CMD; bit++) 782 default_c_bit[bit] = 783 (ACLBYTE(bitarray[bit], u->u_id) & ACLBIT(u->u_id)) ? 1 : 0; 784 } 785 UserDel(u->u_name, NULL); 786 } 787 return 0; 788} 789 790/* 791 * String is broken down into comand and window names, mode applies 792 * A command name matches first, so do not use these as window names. 793 * uu should be NULL, except if you want to change his umask. 794 */ 795int 796AclSetPerm(uu, u, mode, s) 797struct acluser *uu, *u; 798char *mode, *s; 799{ 800 struct win *w; 801 int i; 802 char *p, ch; 803 804 debug3("AclSetPerm(uu, user '%s', mode '%s', object '%s')\n", 805 u->u_name, mode, s); 806 while (*s) 807 { 808 switch (*s) 809 { 810 case '*': /* all windows and all commands */ 811 return AclSetPerm(uu, u, mode, "#?"); 812 case '#': 813 if (uu) /* window umask or .. */ 814 AclSetPermWin(uu, u, mode, (struct win *)1); 815 else /* .. or all windows */ 816 for (w = windows; w; w = w->w_next) 817 AclSetPermWin((struct acluser *)0, u, mode, w); 818 s++; 819 break; 820 case '?': 821 if (uu) /* command umask or .. */ 822 AclSetPermWin(uu, u, mode, (struct win *)0); 823 else /* .. or all commands */ 824 for (i = 0; i <= RC_LAST; i++) 825 AclSetPermCmd(u, mode, &comms[i]); 826 s++; 827 break; 828 default: 829 for (p = s; *p && *p != ' ' && *p != '\t' && *p != ','; p++) 830 ; 831 if ((ch = *p)) 832 *p++ = '\0'; 833 if ((i = FindCommnr(s)) != RC_ILLEGAL) 834 AclSetPermCmd(u, mode, &comms[i]); 835 else if (((i = WindowByNoN(s)) >= 0) && wtab[i]) 836 AclSetPermWin((struct acluser *)0, u, mode, wtab[i]); 837 else 838 /* checking group name */ 839 return -1; 840 if (ch) 841 p[-1] = ch; 842 s = p; 843 } 844 } 845 return 0; 846} 847 848/* 849 * Generic ACL Manager: 850 * 851 * This handles acladd and aclchg identical. 852 * With 2 or 4 parameters, the second parameter is a password. 853 * With 3 or 4 parameters the last two parameters specify the permissions 854 * else user is added with full permissions. 855 * With 1 parameter the users permissions are copied from user *argv. 856 * Unlike the other cases, u->u_name should not match *argv here. 857 * uu should be NULL, except if you want to change his umask. 858 */ 859static int 860UserAcl(uu, u, argc, argv) 861struct acluser *uu, **u; 862int argc; 863char **argv; 864{ 865 if ((*u && !strcmp((*u)->u_name, "nobody")) || 866 (argc > 1 && !strcmp(argv[0], "nobody"))) 867 return -1; /* do not change nobody! */ 868 869 switch (argc) 870 { 871 case 1+1+2: 872 debug2("UserAcl: user '%s', password '%s':", argv[0], argv[1]); 873 return (UserAdd(argv[0], argv[1], u) < 0) || 874 AclSetPerm(uu, *u, argv[2], argv[3]); 875 case 1+2: 876 debug1("UserAcl: user '%s', no password:", argv[0]); 877 return (UserAdd(argv[0], NULL, u) < 0) || 878 AclSetPerm(uu, *u, argv[1], argv[2]); 879 case 1+1: 880 debug2("UserAcl: user '%s', password '%s'\n", argv[0], argv[1]); 881 return UserAdd(argv[0], argv[1], u) < 0; 882 case 1: 883 debug1("UserAcl: user '%s', no password:", argv[0]); 884 return (UserAdd(argv[0], NULL, u) < 0) || 885 AclSetPerm(uu, *u, "+a", "#?"); 886 default: 887 return -1; 888 } 889} 890 891static int 892UserAclCopy(to_up, from_up) 893struct acluser **to_up, **from_up; 894{ 895 struct win *w; 896 int i, j, to_id, from_id; 897 898 if (!*to_up || !*from_up) 899 return -1; 900 debug2("UserAclCopy: from user '%s' to user '%s'\n", 901 (*from_up)->u_name, (*to_up)->u_name); 902 if ((to_id = (*to_up)->u_id) == (from_id = (*from_up)->u_id)) 903 return -1; 904 for (w = windows; w; w = w->w_next) 905 { 906 for (i = 0; i < ACL_BITS_PER_WIN; i++) 907 { 908 if (ACLBYTE(w->w_userbits[i], from_id) & ACLBIT(from_id)) 909 ACLBYTE(w->w_userbits[i], to_id) |= ACLBIT(to_id); 910 else 911 { 912 ACLBYTE(w->w_userbits[i], to_id) &= ~ACLBIT(to_id); 913 if ((w->w_wlockuser == *to_up) && (i == ACL_WRITE)) 914 { 915 debug2("%s lost wlock on win %d\n", 916 (*to_up)->u_name, w->w_number); 917 w->w_wlockuser = NULL; 918 if (w->w_wlock == WLOCK_ON) 919 w->w_wlock = WLOCK_AUTO; 920 } 921 } 922 } 923 } 924 for (j = 0; j <= RC_LAST; j++) 925 { 926 for (i = 0; i < ACL_BITS_PER_CMD; i++) 927 { 928 if (ACLBYTE(comms[j].userbits[i], from_id) & ACLBIT(from_id)) 929 ACLBYTE(comms[j].userbits[i], to_id) |= ACLBIT(to_id); 930 else 931 ACLBYTE(comms[j].userbits[i], to_id) &= ~ACLBIT(to_id); 932 } 933 } 934 935 return 0; 936} 937 938/* 939 * Syntax: 940 * user [password] [+rwx #?] 941 * * [password] [+rwx #?] 942 * user1,user2,user3 [password] [+rwx #?] 943 * user1,user2,user3=user 944 * uu should be NULL, except if you want to change his umask. 945 */ 946int 947UsersAcl(uu, argc, argv) 948struct acluser *uu; 949int argc; 950char **argv; 951{ 952 char *s; 953 int r; 954 struct acluser **cf_u = NULL; 955 956 if (argc == 1) 957 { 958 char *p = NULL; 959 960 s = argv[0]; 961 while (*s) 962 if (*s++ == '=') p = s; 963 if (p) 964 { 965 p[-1] = '\0'; 966 cf_u = FindUserPtr(p); 967 } 968 } 969 970 if (argv[0][0] == '*' && argv[0][1] == '\0') 971 { 972 struct acluser **u; 973 974 debug("all users acls.\n"); 975 for (u = &users; *u; u = &(*u)->u_next) 976 if (strcmp("nobody", (*u)->u_name) && 977 ((cf_u) ? 978 ((r = UserAclCopy(u, cf_u)) < 0) : 979 ((r = UserAcl(uu, u, argc, argv)) < 0))) 980 return -1; 981 return 0; 982 } 983 984 do 985 { 986 for (s = argv[0]; *s && *s!=' ' && *s!='\t' && *s!=',' && *s!='='; s++) 987 ; 988 *s ? (*s++ = '\0') : (*s = '\0'); 989 debug2("UsersAcl(uu, \"%s\", argc=%d)\n", argv[0], argc); 990 if ((cf_u) ? 991 ((r = UserAclCopy(FindUserPtr(argv[0]), cf_u)) < 0) : 992 ((r = UserAcl(uu, FindUserPtr(argv[0]), argc, argv)) < 0)) 993 return -1; 994 } while (*(argv[0] = s)); 995 return 0; 996} 997 998/* 999 * Preprocess argments, so that umask can be set with UsersAcl 1000 * 1001 * all current users umask �rwxn 1002 * one specific user umask user1�rwxn 1003 * several users umask user1,user2,...�rwxn 1004 * default_w_bits umask ?�rwxn 1005 * default_c_bits umask ??�rwxn 1006 */ 1007int 1008AclUmask(u, str, errp) 1009struct acluser *u; 1010char *str; 1011char **errp; 1012{ 1013 char mode[16]; 1014 char *av[3]; 1015 char *p, c = '\0'; 1016 1017 /* split str into user and bits section. */ 1018 for (p = str; *p; p++) 1019 if ((c = *p) == '+' || c == '-') 1020 break; 1021 if (!*p) 1022 { 1023 *errp = "Bad argument. Should be ``[user[,user...]{+|-}rwxn''."; 1024 return -1; 1025 } 1026 strncpy(mode, p, 15); 1027 mode[15] = '\0'; 1028 *p = '\0'; 1029 1030 /* construct argument vector */ 1031 if (!strcmp("??", str)) 1032 { 1033 str++; 1034 av[2] = "?"; 1035 } 1036 else 1037 av[2] = "#"; 1038 av[1] = mode; 1039 av[0] = *str ? str : "*"; 1040 /* call UsersAcl */ 1041 if (UsersAcl(u, 3, av)) 1042 { 1043 *errp = "UsersAcl failed. Hmmm."; 1044 *p = c; 1045 return -1; 1046 } 1047 *p = c; 1048 return 0; 1049} 1050 1051void 1052AclWinSwap(a, b) 1053int a, b; 1054{ 1055 debug2("AclWinSwap(%d, %d) NOP.\n", a, b); 1056} 1057 1058struct acluser *EffectiveAclUser = NULL; /* hook for AT command permission */ 1059 1060int 1061AclCheckPermWin(u, mode, w) 1062struct acluser *u; 1063int mode; 1064struct win *w; 1065{ 1066 int ok; 1067 1068 if (mode < 0 || mode >= ACL_BITS_PER_WIN) 1069 return -1; 1070 if (EffectiveAclUser) 1071 { 1072 debug1("AclCheckPermWin: WARNING user %s overridden!\n", u->u_name); 1073 u = EffectiveAclUser; 1074 } 1075 ok = ACLBYTE(w->w_userbits[mode], u->u_id) & ACLBIT(u->u_id); 1076 debug3("AclCheckPermWin(%s, %d, %d) = ", u->u_name, mode, w->w_number); 1077 1078 if (!ok) 1079 { 1080 struct aclusergroup **g = &u->u_group; 1081 struct acluser *saved_eff = EffectiveAclUser; 1082 1083 EffectiveAclUser = NULL; 1084 while (*g) 1085 { 1086 if (!AclCheckPermWin((*g)->u, mode, w)) 1087 break; 1088 g = &(*g)->next; 1089 } 1090 EffectiveAclUser = saved_eff; 1091 if (*g) 1092 ok = 1; 1093 } 1094 debug1("%d\n", !ok); 1095 return !ok; 1096} 1097 1098int 1099AclCheckPermCmd(u, mode, c) 1100struct acluser *u; 1101int mode; 1102struct comm *c; 1103{ 1104 int ok; 1105 1106 if (mode < 0 || mode >= ACL_BITS_PER_CMD) 1107 return -1; 1108 if (EffectiveAclUser) 1109 { 1110 debug1("AclCheckPermCmd: WARNING user %s overridden!\n", u->u_name); 1111 u = EffectiveAclUser; 1112 } 1113 ok = ACLBYTE(c->userbits[mode], u->u_id) & ACLBIT(u->u_id); 1114 debug3("AclCheckPermCmd(%s %d %s) = ", u->u_name, mode, c->name); 1115 if (!ok) 1116 { 1117 struct aclusergroup **g = &u->u_group; 1118 struct acluser *saved_eff = EffectiveAclUser; 1119 1120 EffectiveAclUser = NULL; 1121 while (*g) 1122 { 1123 if (!AclCheckPermCmd((*g)->u, mode, c)) 1124 break; 1125 g = &(*g)->next; 1126 } 1127 EffectiveAclUser = saved_eff; 1128 if (*g) 1129 ok = 1; 1130 } 1131 debug1("%d\n", !ok); 1132 return !ok; 1133} 1134 1135#endif /* MULTIUSER */ 1136