1 /* 2 * Copyright (C) 2006 The Free Software Foundation, Inc. 3 * 4 * Portions Copyright (C) 2006, Baris Sahin <sbaris at users.sourceforge.net> 5 * <http://cvsacl.sourceforge.net> 6 * 7 * 8 * You may distribute under the terms of the GNU General Public License as 9 * specified in the README file that comes with the CVS source distribution. 10 * 11 * 12 * 13 * CVS ACCESS CONTROL LIST EXTENSION 14 * 15 * It provides advanced access control definitions per modules, 16 * directories, and files on branch/tag for remote cvs repository 17 * connections.Execution of all CVS subcommands can be controlled 18 * with eight different permissions. 19 * 20 * Permission Types: 21 * - no permission (n) (1) 22 * - all permissions (a) (2) 23 * - write permission (w) (3) 24 * - tag permission (t) (4) 25 * - read permission (r) (5) 26 * - add permission (c) (6) 27 * - remove permission (d) (7) 28 * - permission change (p) (8) 29 * 30 */ 31 #include <sys/cdefs.h> 32 __RCSID("$NetBSD: acl.c,v 1.6 2016/05/17 14:00:09 christos Exp $"); 33 34 #include "cvs.h" 35 #include "getline.h" 36 #include <pwd.h> 37 #include <grp.h> 38 39 static int acl_fileproc (void *callerdat, struct file_info *finfo); 40 41 static Dtype acl_dirproc (void *callerdat, const char *dir, const char *repos, 42 const char *update_dir, List *entries); 43 44 static int acllist_fileproc (void *callerdat, struct file_info *finfo); 45 static Dtype acllist_dirproc (void *callerdat, const char *dir, 46 const char *repos, const char *update_dir, 47 List *entries); 48 49 static void acllist_print (char *line, const char *obj); 50 51 static int racl_proc (int argc, char **argv, char *xwhere, 52 char *mwhere, char *mfile, int shorten, 53 int local_specified, char *mname, char *msg); 54 55 static FILE *open_accessfile (char *xmode, const char *repos, char **fname); 56 static FILE *open_groupfile (char *xmode); 57 58 static char *get_perms (const char *xperms); 59 static char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg); 60 61 static char *findusername (const char *string1, const char *string2); 62 static char *findgroupname (const char *string1, const char *string2); 63 static int valid_tag (const char *part_tag, const char *tag); 64 static int valid_perm (const char *part_perms, int perm); 65 static int write_perms (const char *user, const char *perms, 66 const char *founduserpart, int foundline, 67 char *otheruserparts, const char *part_type, 68 const char *part_object, const char *part_tag, int pos, 69 const char *arepos); 70 71 static char *cache_repository; 72 static int cache_retval; 73 static int founddeniedfile; 74 static int cache_perm; 75 76 static int is_racl; 77 static int debug = 0; 78 79 int use_cvs_acl = 0; 80 char *cvs_acl_default_permissions; 81 int use_cvs_groups = 0; 82 int use_system_groups = 0; 83 int use_separate_acl_file_for_each_dir = 0; 84 char *cvs_acl_file_location = NULL; 85 char *cvs_groups_file_location = NULL; 86 char *cvs_server_run_as = NULL; 87 int stop_at_first_permission_denied = 0; 88 89 char *tag = NULL; 90 91 char *muser; 92 char *mperms; 93 static int defaultperms; 94 95 static char *default_perms_object; 96 char *default_part_perms_accessfile; 97 int aclconfig_default_used; 98 99 int acldir = 0; 100 int aclfile = 0; 101 int listacl = 0; 102 103 int userfound = 0; 104 int groupfound = 0; 105 106 /* directory depth ... */ 107 char *dirs[255]; 108 109 static const char *const acl_usage[] = 110 { 111 "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...] [files...]\n", 112 "\t-R\tProcess directories recursively.\n", 113 "\t-r rev\tExisting revision/tag.\n", 114 "\t-l\tList defined ACLs.\n", 115 "(Specify the --help global option for a list of other help options)\n", 116 NULL 117 }; 118 119 static const char *const racl_usage[] = 120 { 121 "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...]" 122 " [files...]\n", 123 "\t-R\tProcess directories recursively.\n", 124 "\t-r rev\tExisting revision/tag.\n", 125 "\t-l\tList defined ACLs.\n", 126 "(Specify the --help global option for a list of other help options)\n", 127 NULL 128 }; 129 130 131 int 132 access_allowed (const char *file, const char *repos, const char *tag, 133 int perm, char **mline, int *mpos, int usecache) 134 { 135 int retval = 0; 136 int foundline = 0; 137 FILE *accessfp; 138 139 int flag = 1; 140 141 char *iline; 142 char *tempv; 143 char *tempc; 144 size_t tempsize; 145 146 int intcount; 147 int accessfilecount; 148 int signlevel = -1; 149 int dadmin = 0; 150 151 const char *repository; 152 char *filefullname = NULL; 153 userfound = 0; 154 groupfound = 0; 155 156 if (defaultperms) 157 { 158 repository = xstrdup ("ALL"); 159 } 160 else { 161 if (strlen(repository = Short_Repository (repos)) == 0) 162 { 163 repository = xstrdup ("."); 164 } 165 } 166 167 /* cache */ 168 if (usecache && cache_repository != NULL && 169 strcmp (cache_repository, repository) == 0 && !founddeniedfile 170 && perm == cache_perm) 171 return (cache_retval); 172 else 173 { 174 free (cache_repository); 175 cache_repository = xstrdup (repository); 176 cache_perm = perm; 177 } 178 179 iline = xstrdup(repository); 180 181 tempv = strtok(iline, "/\t"); 182 tempc = xstrdup(tempv); 183 tempsize = ( tempc != NULL ) ? strlen(tempc) : 0; 184 185 intcount = 0; 186 /* store paths from object to cvsroot */ 187 dirs[intcount] = xstrdup(tempc); 188 while ((tempv = strtok(NULL, "/\t")) != NULL) 189 { 190 intcount++; 191 192 xrealloc_and_strcat(&tempc, &tempsize, "/"); 193 xrealloc_and_strcat(&tempc, &tempsize, tempv); 194 195 dirs[intcount] = xstrdup(tempc); 196 } 197 198 /* free not needed variables here */ 199 free (tempv); 200 free (tempc); 201 free (iline); 202 203 /* accessfilecount will used 204 * if UseSeparateACLFile keyword is set to yes*/ 205 accessfilecount = intcount; 206 207 /* if file is not null add it to dirs array */ 208 if (file != NULL) 209 { 210 filefullname = Xasprintf("%s/%s", repository, file); 211 intcount++; 212 dirs[intcount] = xstrdup(filefullname); 213 } 214 215 for (; accessfilecount >= 0 && flag; accessfilecount--) 216 { 217 if (!use_separate_acl_file_for_each_dir) { 218 flag = 0; 219 accessfp = open_accessfile ("r", repository, NULL); 220 } 221 else 222 { 223 flag = 1; 224 accessfp = open_accessfile ("r", dirs[accessfilecount], NULL); 225 } 226 227 if (accessfp != NULL) 228 { 229 char *line = NULL; 230 size_t line_allocated = 0; 231 232 char *xline; 233 char *part_type = NULL; 234 char *part_object = NULL; 235 char *part_tag = NULL; 236 char *part_perms = NULL; 237 238 int x; 239 240 while (getline (&line, &line_allocated, accessfp) >= 0) 241 { 242 243 if (line[0] == '#' || line[0] == '\0' || line[0] == '\n') 244 continue; 245 246 xline = xstrdup (line); 247 part_type = strtok (line, ":\t"); 248 part_object = strtok (NULL, ":\t"); 249 part_tag = strtok (NULL, ":\t"); 250 part_perms = strtok (NULL, ":\t"); 251 252 if (part_type == NULL || part_object == NULL || 253 part_tag == NULL || part_perms == NULL) 254 { 255 free (line); 256 error(1, 0, "access file is corrupted or has invalid" 257 " format"); 258 } 259 260 if (debug) fprintf (stderr, "type %s object %s tag %s perms" 261 "%s\n", part_type, part_object, part_tag, 262 part_perms); 263 for (x = intcount; x >= signlevel && x != -1; x--) 264 { 265 if (debug) fprintf (stderr, "dirs[%d] = %s, part_object=" 266 "%s\n", x, dirs[x], part_object); 267 if (strcmp (dirs[x], part_object) == 0) 268 { 269 if (debug) fprintf(stderr, "tag %s \n", tag); 270 if (valid_tag (part_tag, tag)) 271 { 272 foundline = 1; 273 if (debug) fprintf(stderr, "foundline\n"); 274 275 if (listacl || ((acldir || aclfile) && 276 x == intcount) && 277 strcmp(part_tag, tag) == 0) 278 { 279 *mline = xstrdup (xline); 280 *mpos = ftell (accessfp); 281 } 282 283 if (debug) fprintf(stderr, "perm %d\n", perm); 284 if (valid_perm (part_perms, perm)) 285 { 286 if (debug) fprintf(stderr, "signlevel=%d " 287 " x=%d, aclconfig_default_used=%d\n", 288 signlevel, x, aclconfig_default_used); 289 if (signlevel == x) 290 { 291 if (strcmp(part_tag, "ALL") != 0 && 292 !aclconfig_default_used) { 293 retval = 1; 294 if (debug) fprintf(stderr, 295 "%s, %d: %d\n", __FILE__, __LINE__, 296 retval); 297 } 298 } 299 else if (!aclconfig_default_used) 300 { 301 signlevel = x; 302 retval = 1; 303 if (debug) fprintf(stderr, 304 "%s, %d: %d\n", __FILE__, __LINE__, 305 retval); 306 } 307 else { 308 /* nothing... */ 309 } 310 } 311 else 312 { 313 if (signlevel == x) 314 { 315 if (strcmp(part_tag, "ALL") != 0 && 316 !aclconfig_default_used) { 317 retval = 0; 318 if (debug) fprintf(stderr, 319 "%s, %d: %d\n", __FILE__, __LINE__, 320 retval); 321 } 322 } 323 else if (!aclconfig_default_used) 324 { 325 signlevel = x; 326 retval = 0; 327 if (debug) fprintf(stderr, 328 "%s, %d: %d\n", __FILE__, __LINE__, 329 retval); 330 331 if (strncmp (part_type, "f", 1) == 0) 332 founddeniedfile = 1; 333 } 334 else { 335 } 336 } 337 } 338 } 339 } 340 341 if (debug) fprintf (stderr, "xline tag = %s %d %d\n", xline, 342 groupfound, userfound); 343 if (strncmp (xline, "d:ALL:", 6) == 0 && 344 ((!groupfound && !userfound) || listacl)) 345 { 346 if (debug) fprintf (stderr, "ALL tag = %s\n", tag); 347 /* a default found */ 348 if (valid_tag (part_tag, tag) > 0) 349 { 350 foundline = 1; 351 352 default_part_perms_accessfile = xstrdup (part_perms); 353 354 if (debug) fprintf (stderr, "valid perm = %d\n", perm); 355 if (valid_perm (part_perms, perm)) 356 { 357 retval = 1; 358 if (debug) fprintf(stderr, 359 "%s, %d: %d\n", __FILE__, __LINE__, 360 retval); 361 if (perm == 8) 362 dadmin = 1; 363 } 364 else { 365 retval = 0; 366 if (debug) fprintf(stderr, 367 "%s, %d: %d\n", __FILE__, __LINE__, 368 retval); 369 } 370 } 371 } 372 373 } 374 375 if (fclose (accessfp) == EOF) 376 error (1, errno, "cannot close 'access' file"); 377 } 378 } 379 380 if (!foundline) 381 { 382 if (debug) fprintf(stderr, "not found line\n"); 383 /* DEFAULT */ 384 if (valid_perm (NULL, perm)) { 385 retval = 1; 386 if (debug) fprintf(stderr, 387 "%s, %d: %d\n", __FILE__, __LINE__, 388 retval); 389 } else { 390 retval = 0; 391 if (debug) fprintf(stderr, 392 "%s, %d: %d\n", __FILE__, __LINE__, 393 retval); 394 } 395 } 396 397 /* acl admin rigths 'p' */ 398 if (dadmin) 399 { 400 retval = dadmin; 401 } 402 403 cache_retval = retval; 404 405 free (filefullname); 406 /* free directories array */ 407 while (intcount >= 0) 408 { 409 free (dirs[intcount]); 410 intcount--; 411 } 412 413 return retval; 414 } 415 416 /* Returns 1 if tag is valid, 0 if not */ 417 static int 418 valid_tag (const char *part_tag, const char *tag) 419 { 420 int retval; 421 422 if (tag == NULL) 423 tag = "HEAD"; 424 425 if (strcmp (tag, part_tag) == 0 || strcmp (part_tag, "ALL") == 0) 426 retval = 1; 427 else 428 retval = 0; 429 430 return retval; 431 } 432 433 /* Returns 1 if successful, 0 if not. */ 434 static int 435 valid_perm (const char *part_perms, int perm) 436 { 437 char *perms; 438 int retval = 0; 439 440 perms = get_perms (part_perms); 441 442 /* Allow, if nothing found. */ 443 if (perms[0] == '\0') 444 return (1); 445 446 /* no access allowed, exit */ 447 if (strstr (perms, "n")) 448 retval = 0; 449 450 if (strstr (perms, "p")) 451 /* admin rights */ 452 retval = 1; 453 else if (strstr (perms, "a") && perm != 8) 454 /* all access allowed, exit */ 455 retval = 1; 456 else 457 switch (perm) 458 { 459 case 3:/* write permission */ 460 if (strstr (perms, "w")) 461 retval = 1; 462 break; 463 case 4:/* tag permission */ 464 if (strstr (perms, "t")) 465 retval = 1; 466 break; 467 case 5:/* read permission */ 468 if (strstr (perms, "w") || strstr (perms, "t") || 469 strstr (perms, "c") || strstr (perms, "d") || 470 strstr (perms, "r")) 471 retval = 1; 472 break; 473 case 6:/* create permission */ 474 if (strstr (perms, "c")) 475 retval = 1; 476 break; 477 case 7:/* delete permission */ 478 if (strstr (perms, "d")) 479 retval = 1; 480 break; 481 case 8:/* permission change */ 482 if (strstr (perms, "p")) 483 retval = 1; 484 break; 485 default:/* never reached */ 486 retval = 0; 487 break; 488 } 489 490 free (perms); 491 492 return (retval); 493 } 494 495 /* returns permissions found */ 496 char * 497 get_perms (const char *part_perms) 498 { 499 char *username; 500 char *xperms; 501 size_t xperms_len = 1; 502 503 FILE *groupfp; 504 505 char *founduser = NULL; 506 char *foundall = NULL; 507 int default_checked = 0; 508 509 if (debug) fprintf (stderr, "get_perms %s...", part_perms); 510 aclconfig_default_used = 0; 511 512 xperms = xmalloc (xperms_len); 513 xperms[0] = '\0'; 514 515 /* use CVS_Username if set */ 516 if (CVS_Username == NULL) 517 username = getcaller (); 518 else 519 username = CVS_Username; 520 521 /* no defined acl, no default acl in access file, 522 * or no access file at all */ 523 if (part_perms == NULL) { 524 if (cvs_acl_default_permissions) 525 { 526 aclconfig_default_used = 1; 527 if (debug) fprintf (stderr, "default %s\n", 528 cvs_acl_default_permissions); 529 return xstrdup(cvs_acl_default_permissions); 530 } 531 else { 532 if (debug) fprintf (stderr, "early %s\n", xperms); 533 return xperms; 534 } 535 } 536 537 check_default: 538 founduser = findusername (part_perms, username); 539 foundall = strstr (part_perms, "ALL!"); 540 541 if (debug) fprintf (stderr, "founduser=%s foundALL=%s\n", 542 founduser, foundall); 543 if (founduser) 544 { 545 char *usr; 546 char *per; 547 548 usr = strtok (founduser, "!\t"); 549 per = strtok (NULL, ",\t"); 550 551 free(xperms); 552 xperms = xstrdup (per); 553 xperms_len = strlen (xperms); 554 555 userfound = 1; 556 free (founduser); 557 } 558 else 559 { 560 if (debug) fprintf (stderr, "usesystemgroups=%d\n", use_system_groups); 561 if (use_system_groups) { 562 struct group *griter; 563 struct passwd *pwd; 564 gid_t gid = (pwd = getpwnam(username)) != NULL ? pwd->pw_gid : -1; 565 setgrent (); 566 while (griter = getgrent ()) 567 { 568 char *userchk; 569 if (gid == griter->gr_gid) { 570 userchk = username; 571 } else { 572 char **users = griter->gr_mem; 573 int index = 0; 574 userchk = users [index++]; 575 while(userchk != NULL) { 576 if(strcmp (userchk, username) == 0) 577 break; 578 userchk = users[index++]; 579 } 580 } 581 if (userchk != NULL) { 582 char *grp; 583 if ((grp = findusername (part_perms, griter->gr_name))) 584 { 585 char *gperm = strtok (grp, "!\t"); 586 if (debug) fprintf (stderr, "usercheck=%s, grp=%s\n", 587 userchk, grp); 588 gperm = strtok (NULL, ",\t"); 589 xrealloc_and_strcat (&xperms, &xperms_len, gperm); 590 591 groupfound = 1; 592 free (grp); 593 } 594 } 595 } 596 endgrent (); 597 } 598 else if (use_cvs_groups) { 599 groupfp = open_groupfile ("r"); 600 if (groupfp != NULL) 601 { 602 char *line = NULL; 603 char *grp; 604 char *gperm; 605 int read; 606 607 size_t line_allocated = 0; 608 609 while ((read = getline (&line, &line_allocated, groupfp)) >= 0) 610 { 611 char *user; 612 if (line[0] == '#' || line[0] == '\0' || line[0] == '\n') 613 continue; 614 615 if (line[read - 1] == '\n') 616 line[--read] = '\0'; 617 618 if ((grp = findgroupname (line, username)) && 619 (user = findusername (part_perms, grp))) 620 621 { 622 gperm = strtok (user, "!\t"); 623 gperm = strtok (NULL, ",\t"); 624 xrealloc_and_strcat (&xperms, &xperms_len, gperm); 625 groupfound = 1; 626 free (grp); 627 free (user); 628 } 629 } 630 631 free (line); 632 633 if (fclose (groupfp) == EOF) 634 error (1, errno, "cannot close 'group' file"); 635 } 636 } 637 } 638 639 if (foundall) 640 { 641 char *usr; 642 char *per; 643 644 usr = strtok (strstr (part_perms, "ALL!"), "!\t"); 645 per = strtok (NULL, ",\t"); 646 647 if (!default_checked) 648 default_perms_object = xstrdup (per); 649 650 if (xperms[0] == '\0') 651 { 652 xperms = xstrdup (per); 653 xperms_len = strlen (xperms); 654 } 655 656 /* You don't free pointers from strtok()! */ 657 //free(usr); 658 //free(per); 659 } 660 661 if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile) 662 { 663 part_perms = xstrdup (default_part_perms_accessfile); 664 default_checked = 1; 665 666 goto check_default; 667 } 668 669 if (xperms[0] != '\0' && strcmp (xperms, "x") == 0) 670 { 671 if (default_perms_object) 672 xperms = xstrdup (default_perms_object); 673 else if (default_part_perms_accessfile) 674 { 675 part_perms = default_part_perms_accessfile; 676 default_checked = 1; 677 goto check_default; 678 } 679 else if (cvs_acl_default_permissions) 680 { 681 aclconfig_default_used = 1; 682 xperms = xstrdup (cvs_acl_default_permissions); 683 } 684 } 685 686 if (xperms[0] == '\0' && cvs_acl_default_permissions) 687 { 688 aclconfig_default_used = 1; 689 xperms = xstrdup (cvs_acl_default_permissions); 690 } 691 692 if (debug) fprintf (stderr, "late %s\n", xperms); 693 return xperms; 694 } 695 696 697 int 698 cvsacl (int argc, char **argv) 699 { 700 char *chdirrepository; 701 int c; 702 int err = 0; 703 int usetag = 0; 704 int recursive = 0; 705 706 int which; 707 char *where; 708 709 is_racl = (strcmp (cvs_cmd_name, "racl") == 0); 710 711 if (argc == -1) 712 usage (is_racl ? racl_usage : acl_usage); 713 714 /* parse the args */ 715 optind = 0; 716 717 while ((c = getopt (argc, argv, "dRr:l")) != -1) 718 { 719 switch (c) 720 { 721 case 'd': 722 debug++; 723 break; 724 case 'R': 725 recursive = 1; 726 break; 727 case 'r': // baris 728 tag = xstrdup (optarg); 729 break; 730 case 'l': 731 listacl = 1; 732 break; 733 case '?': 734 default: 735 usage (is_racl ? racl_usage : acl_usage); 736 break; 737 } 738 } 739 740 argc -= optind; 741 argv += optind; 742 743 if (argc < (is_racl ? 1 : 1)) 744 usage (is_racl ? racl_usage : acl_usage); 745 if (listacl) { 746 if (strstr (argv[0], ":")) 747 usage (is_racl ? racl_usage : acl_usage); 748 } else { 749 if (!strstr (argv[0], ":")) 750 usage (is_racl ? racl_usage : acl_usage); 751 } 752 753 754 #ifdef CLIENT_SUPPORT 755 756 if (current_parsed_root->isremote) 757 { 758 start_server (); 759 ign_setup (); 760 761 if(recursive) 762 send_arg ("-R"); 763 764 if (listacl) 765 send_arg ("-l"); 766 767 if(tag) 768 { 769 option_with_arg ("-r", tag); 770 } 771 772 send_arg ("--"); 773 774 if (!listacl) 775 { 776 send_arg (argv[0]); 777 778 argc--; 779 argv++; 780 } 781 782 if (is_racl) 783 { 784 int i; 785 for (i = 0; i < argc; ++i) 786 send_arg (argv[i]); 787 788 send_to_server ("racl\012",0); 789 } 790 else 791 { 792 send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS); 793 send_file_names (argc, argv, SEND_EXPAND_WILD); 794 send_to_server ("acl\012", 0); 795 } 796 797 return get_responses_and_close (); 798 } 799 #endif 800 801 #ifdef SERVER_SUPPORT 802 803 if (!listacl) 804 { 805 muser = strtok (argv[0], ":\t"); 806 mperms = strtok (NULL, ":\t"); 807 808 /* if set to 'default' */ 809 if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0)) 810 mperms = xstrdup ("x"); 811 812 /* Check that the given permissions are valid. */ 813 if (!given_perms_valid (mperms)) 814 error (1,0,"Invalid permissions: `%s'", mperms); 815 816 argc--; 817 argv++; 818 } 819 820 821 if (!tag) 822 tag = xstrdup ("HEAD"); 823 824 if (!strcasecmp (argv[0], "ALL")) 825 { 826 argv[0] = xstrdup ("."); 827 defaultperms = 1; 828 if (!use_separate_acl_file_for_each_dir) 829 { 830 recursive = 0; 831 } 832 833 } 834 835 if (is_racl) 836 { 837 DBM *db; 838 int i; 839 db = open_module (); 840 for (i = 0; i < argc; i++) 841 { 842 err += do_module (db, argv[i], MISC, "ACL ing: ", 843 racl_proc, NULL, 0, !recursive, 0, 844 0, NULL); 845 } 846 close_module (db); 847 } 848 else 849 { 850 err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive, 851 NULL, NULL); 852 } 853 854 return err; 855 856 #endif 857 } 858 859 static int 860 racl_proc (int argc, char **argv, char *xwhere, char *mwhere, 861 char *mfile, int shorten, int local, char *mname, char *msg) 862 { 863 char *myargv[2]; 864 int err = 0; 865 int which; 866 char *repository; 867 char *where; 868 char *obj; 869 size_t objlen = 0; 870 871 if (!use_cvs_acl) 872 { 873 error(1, 0, "CVSACL extension is not enabled, set `UseCVSACL=yes'" 874 " in aclconfig file"); 875 } 876 877 if (is_racl) 878 { 879 char *v; 880 repository = Xasprintf ("%s/%s", current_parsed_root->directory, 881 argv[0]); 882 where = xstrdup (argv[0]); 883 884 /* if mfile isn't null, we need to set up to do only part of the 885 * module */ 886 if (mfile != NULL) 887 { 888 char *cp; 889 char *path; 890 891 /* if the portion of the module is a path, put the dir part on 892 * repos */ 893 if ((cp = strrchr (mfile, '/')) != NULL) 894 { 895 *cp = '\0'; 896 v = Xasprintf ("%s/%s", repository, mfile); 897 free (repository); 898 repository = v; 899 v = Xasprintf ("%s/%s", where, mfile); 900 free(where); 901 where = v; 902 mfile = cp + 1; 903 } 904 905 /* take care of the rest */ 906 path = Xasprintf ("%s/%s", repository, mfile); 907 if (isdir (path)) 908 { 909 /* directory means repository gets the dir tacked on */ 910 free(repository); 911 repository = path; 912 v = Xasprintf ("%s/%s", where, mfile); 913 free(where); 914 where = v; 915 } 916 else 917 { 918 free (path); 919 myargv[0] = argv[0]; 920 myargv[1] = mfile; 921 argc = 2; 922 argv = myargv; 923 } 924 } 925 926 /* cd to the starting repository */ 927 if ( CVS_CHDIR (repository) < 0) 928 { 929 error (0, errno, "cannot chdir to %s", repository); 930 free (repository); 931 free (where); 932 return 1; 933 } 934 935 /* End section which is identical to patch_proc. */ 936 937 which = W_REPOS | W_ATTIC; 938 939 if (argc > 1) 940 { 941 obj = Xasprintf ("%s/%s", repository, argv[1]); 942 } 943 else 944 { 945 obj = xstrdup(repository); 946 } 947 } 948 else 949 { 950 where = NULL; 951 repository = NULL; 952 which = W_LOCAL | W_REPOS | W_ATTIC; 953 954 obj = xstrdup (argv[1]); 955 } 956 957 if (isdir (obj)) 958 acldir = 1; 959 else if (isfile (obj)) 960 aclfile = 1; 961 else 962 error(1, 0, "no such file or directory"); 963 964 free (obj); 965 966 if (listacl) 967 err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL, 968 NULL, argc - 1, argv + 1, local, which, 0, 0, 969 where, 1, repository); 970 else 971 err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL, 972 argc - 1, argv + 1, local, which, 0, 0, 973 where, 1, repository); 974 975 if (repository != NULL) 976 free (repository); 977 if (where != NULL) 978 free (where); 979 980 return err; 981 } 982 983 984 static int 985 acl_fileproc (void *callerdat, struct file_info *finfo) 986 { 987 char *filefullname; 988 char *founduserpart = NULL; 989 char *otheruserparts = NULL; 990 size_t otherslen = 0; 991 992 const char *frepository; 993 int foundline = 0; 994 995 char *line = NULL; 996 size_t line_allocated = 0; 997 int linelen; 998 999 char *wperms; 1000 char *errmsg; 1001 1002 int pos; 1003 1004 if (!aclfile) 1005 return 0; 1006 1007 frepository = Short_Repository (finfo->repository); 1008 1009 filefullname = Xasprintf("%s/%s", frepository, finfo->file); 1010 1011 1012 if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos, 1013 0)) 1014 error (1, 0, "You do not have acl admin rights on '%s'", frepository); 1015 1016 if (line != NULL) 1017 { 1018 char *part_type = NULL; 1019 char *part_object = NULL; 1020 char *part_tag = NULL; 1021 char *part_perms = NULL; 1022 char *userpart; 1023 1024 part_type = strtok (line, ":\t"); 1025 part_object = strtok (NULL, ":\t"); 1026 part_tag = strtok (NULL, ":\t"); 1027 part_perms = strtok (NULL, ":\t"); 1028 1029 foundline = 1; 1030 userpart = strtok (part_perms, ",\t"); 1031 1032 do 1033 { 1034 if (strncmp (userpart, muser, strlen (muser)) == 0) 1035 founduserpart = xstrdup (userpart); 1036 else 1037 { 1038 if (otheruserparts != NULL) 1039 { 1040 xrealloc_and_strcat (&otheruserparts, &otherslen, ","); 1041 xrealloc_and_strcat (&otheruserparts, &otherslen, userpart); 1042 } 1043 else 1044 { 1045 otheruserparts = xstrdup (userpart); 1046 otherslen = strlen (otheruserparts); 1047 } 1048 } 1049 } while ((userpart = strtok (NULL, ",\t")) != NULL); 1050 1051 free (userpart); 1052 } 1053 1054 wperms = make_perms (mperms, founduserpart, &errmsg); 1055 if (wperms == NULL) 1056 { 1057 if (errmsg) 1058 error (0, 0, "`%s' %s", filefullname, errmsg); 1059 } 1060 else 1061 { 1062 cvs_output ("X ", 0); 1063 cvs_output (filefullname, 0); 1064 cvs_output ("\n", 0); 1065 1066 write_perms (muser, wperms, founduserpart, foundline, 1067 otheruserparts, "f", filefullname, tag, pos, 1068 Short_Repository(finfo->repository)); 1069 } 1070 1071 free (line); 1072 free (founduserpart); 1073 free (otheruserparts); 1074 free (wperms); 1075 free (filefullname); 1076 1077 return 0; 1078 } 1079 1080 static Dtype 1081 acl_dirproc (void *callerdat, const char *dir, const char *repos, 1082 const char *update_dir, List *entries) 1083 { 1084 const char *drepository; 1085 char *founduserpart = NULL; 1086 char *otheruserparts = NULL; 1087 size_t otherslen = 0; 1088 int foundline = 0; 1089 1090 char *line = NULL; 1091 size_t line_allocated = 0; 1092 int linelen; 1093 1094 int pos; 1095 1096 char *wperms; 1097 char *errmsg; 1098 1099 if (!acldir) 1100 return 0; 1101 1102 if (repos[0] == '\0') 1103 repos = Name_Repository (dir, NULL); 1104 1105 if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0)) 1106 error (1, 0, "You do not have admin rights on '%s'", 1107 Short_Repository (repos)); 1108 1109 drepository = Short_Repository (repos); 1110 1111 if (line != NULL) 1112 { 1113 char *part_type = NULL; 1114 char *part_object = NULL; 1115 char *part_tag = NULL; 1116 char *part_perms = NULL; 1117 char *userpart; 1118 1119 part_type = strtok (line, ":\t"); 1120 part_object = strtok (NULL, ":\t"); 1121 part_tag = strtok (NULL, ":\t"); 1122 part_perms = strtok (NULL, ":\t"); 1123 1124 foundline = 1; 1125 userpart = strtok (part_perms, ",\t"); 1126 1127 do 1128 { 1129 if (strncmp (userpart, muser, strlen (muser)) == 0) 1130 founduserpart = xstrdup (userpart); 1131 else 1132 { 1133 if (otheruserparts != NULL) 1134 { 1135 xrealloc_and_strcat (&otheruserparts, &otherslen, ","); 1136 xrealloc_and_strcat (&otheruserparts, &otherslen, userpart); 1137 } 1138 else 1139 { 1140 otheruserparts = xstrdup (userpart); 1141 otherslen = strlen (otheruserparts); 1142 } 1143 } 1144 } while ((userpart = strtok (NULL, ",\t")) != NULL); 1145 } 1146 1147 wperms = make_perms (mperms, founduserpart, &errmsg); 1148 if (wperms == NULL) 1149 { 1150 if (errmsg) 1151 error (0, 0, "`%s' %s", drepository, errmsg); 1152 } 1153 else 1154 { 1155 if (defaultperms) 1156 { 1157 cvs_output ("X ", 0); 1158 cvs_output ("ALL", 0); 1159 cvs_output ("\n", 0); 1160 write_perms (muser, wperms, founduserpart, foundline, 1161 otheruserparts, "d", "ALL", tag, pos, drepository); 1162 1163 } 1164 else 1165 { 1166 cvs_output ("X ", 0); 1167 cvs_output (drepository, 0); 1168 cvs_output ("\n", 0); 1169 write_perms (muser, wperms, founduserpart, foundline, 1170 otheruserparts, "d", drepository, tag, pos, 1171 drepository); 1172 } 1173 } 1174 1175 free (line); 1176 free (founduserpart); 1177 free (otheruserparts); 1178 free (wperms); 1179 1180 return 0; 1181 } 1182 1183 /* Open CVSROOT/access or defined CVSACLFileLocation file 1184 * Open access file In each directory if UseSeparateACLFileForEachDir=yes 1185 * returns file pointer to access file or NULL if access file not found */ 1186 FILE * 1187 open_accessfile (char *fmode, const char *adir, char **fname) 1188 { 1189 char *accessfile = NULL; 1190 FILE *accessfp; 1191 1192 if (!use_separate_acl_file_for_each_dir) 1193 { 1194 if (cvs_acl_file_location == NULL) 1195 { 1196 accessfile = Xasprintf("%s/%s/%s", current_parsed_root->directory, 1197 CVSROOTADM, CVSROOTADM_ACCESS); 1198 } 1199 else 1200 { 1201 accessfile = xstrdup(cvs_acl_file_location); 1202 } 1203 } 1204 else 1205 { 1206 size_t accessfilelen = 0; 1207 xrealloc_and_strcat (&accessfile, &accessfilelen, 1208 current_parsed_root->directory); 1209 xrealloc_and_strcat (&accessfile, &accessfilelen, "/"); 1210 xrealloc_and_strcat (&accessfile, &accessfilelen, adir); 1211 xrealloc_and_strcat (&accessfile, &accessfilelen, "/access"); 1212 } 1213 1214 accessfp = CVS_FOPEN (accessfile, fmode); 1215 1216 if (fname != NULL) 1217 *fname = xstrdup (accessfile); 1218 1219 free (accessfile); 1220 1221 return accessfp; 1222 } 1223 1224 /* Open /etc/group file if UseSystemGroups=yes in config file 1225 * Open CVSROOT/group file if UseCVSGroups=yes in config file 1226 * Open group file if specified in CVSGroupsFileLocation 1227 * returns group file pointer if UseSystemGroups=yes 1228 * returns NULL if UseSystemGroups=no or group file not found */ 1229 FILE * 1230 open_groupfile (char *fmode) 1231 { 1232 char *groupfile; 1233 FILE *groupfp; 1234 1235 if (use_cvs_groups) 1236 { 1237 if (cvs_groups_file_location != NULL) 1238 { 1239 groupfile = xstrdup (cvs_groups_file_location); 1240 } 1241 else 1242 { 1243 groupfile = Xasprintf("%s/%s/%s", current_parsed_root->directory, 1244 CVSROOTADM, CVSROOTADM_GROUP); 1245 } 1246 } 1247 else 1248 { 1249 return NULL; 1250 } 1251 1252 groupfp = CVS_FOPEN (groupfile, "r"); 1253 1254 if (groupfp == NULL) 1255 error (0, 0, "cannot open file: %s", groupfile); 1256 1257 free (groupfile); 1258 1259 return groupfp; 1260 } 1261 1262 1263 /* Check whether given permissions are valid or not 1264 * Returns 1 if permissions are valid 1265 * Returns 0 if permissions are NOT valid */ 1266 int 1267 given_perms_valid (const char *cperms) 1268 { 1269 int cperms_len; 1270 int retval; 1271 int index, i; 1272 1273 if (cperms[0] == '+' || cperms[0] == '-') 1274 index = 1; 1275 else 1276 index = 0; 1277 1278 cperms_len = strlen (cperms); 1279 1280 switch (cperms[index]) 1281 { 1282 case 'x': 1283 if ((cperms_len - index) == 1 && cperms_len == 1) 1284 retval = 1; 1285 else 1286 retval = 0; 1287 break; 1288 case 'n': 1289 if ((cperms_len - index) == 1 && cperms_len == 1) 1290 retval = 1; 1291 else 1292 retval = 0; 1293 break; 1294 case 'p': 1295 if ((cperms_len - index) == 1) 1296 retval = 1; 1297 else 1298 retval = 0; 1299 break; 1300 case 'a': 1301 if ((cperms_len - index) == 1) 1302 retval = 1; 1303 else 1304 retval = 0; 1305 break; 1306 case 'r': 1307 if ((cperms_len - index) == 1) 1308 retval = 1; 1309 else 1310 retval = 0; 1311 break; 1312 case 'w': 1313 if ((cperms_len - index) == 1) 1314 retval = 1; 1315 else 1316 for (i = index + 1; i < cperms_len; i++) 1317 if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd') 1318 retval = 1; 1319 else 1320 retval = 0; 1321 break; 1322 case 't': 1323 if ((cperms_len - index) == 1) 1324 retval = 1; 1325 else 1326 for (i = index + 1; i < cperms_len; i++) 1327 if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd') 1328 retval = 1; 1329 else 1330 retval = 0; 1331 break; 1332 case 'c': 1333 if ((cperms_len - index) == 1) 1334 retval = 1; 1335 else 1336 for (i = index + 1; i < cperms_len; i++) 1337 if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd') 1338 retval = 1; 1339 else 1340 retval = 0; 1341 break; 1342 case 'd': 1343 if ((cperms_len - index) == 1) 1344 retval = 1; 1345 else 1346 for (i = index + 1; i < cperms_len; i++) 1347 if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w') 1348 retval = 1; 1349 else 1350 retval = 0; 1351 break; 1352 default: 1353 retval = 0; 1354 break; 1355 } 1356 1357 return retval; 1358 } 1359 1360 /* prepare permsissions string to be written to access file 1361 * returns permissions or NULL if */ 1362 char * 1363 make_perms (char *perms, char *founduserpart, char **xerrmsg) 1364 { 1365 char *fperms = NULL; 1366 size_t perms_len; 1367 size_t fperms_len; 1368 1369 int i, j; 1370 int err = 0; 1371 char *errmsg = NULL; 1372 1373 char *retperms; 1374 size_t retperms_len; 1375 1376 perms_len = strlen (perms); 1377 if (perms[0] == '+' || perms[0] == '-') 1378 { 1379 retperms = xmalloc (retperms_len); 1380 retperms[0] = '\0'; 1381 retperms_len = 1; 1382 1383 if (founduserpart) 1384 { 1385 char *tempfperms; 1386 size_t tempfperms_len; 1387 1388 char *temp; 1389 int per = 0; 1390 temp = strtok (founduserpart, "!\t"); 1391 fperms = strtok (NULL, "!\t"); 1392 fperms_len = strlen (fperms); 1393 1394 if (strncmp (fperms, "x", 1) == 0) 1395 { 1396 err = 1; 1397 if (perms[0] == '+') 1398 *xerrmsg = xstrdup ("cannot add default permission 'x'"); 1399 else 1400 *xerrmsg = xstrdup ("cannot remove default permission 'x'"); 1401 } 1402 1403 /* go through perms */ 1404 for (i = 1; i < perms_len && !err; i++) 1405 { 1406 switch (perms[i]) 1407 { 1408 case 'n': 1409 err = 1; 1410 break; 1411 case 'p': 1412 if (perms[0] == '+') 1413 fperms = xstrdup ("p"); 1414 else if (perms[0] == '-') 1415 { 1416 fperms_len = 1; 1417 fperms = xmalloc (fperms_len); 1418 fperms[0] = '\0'; 1419 } 1420 break; 1421 case 'a': 1422 for (j = 0; j < fperms_len; j++) 1423 { 1424 if (fperms[j] == 'p') 1425 { 1426 err = 1; 1427 *xerrmsg = xstrdup ("user have admin rights," 1428 " cannot use +/- permissions"); 1429 } 1430 else if (fperms[j] == 'a' && perms[0] == '+') 1431 { 1432 err = 1; 1433 *xerrmsg = xstrdup ("user already has all ('a')" 1434 " permission"); 1435 } 1436 else if (fperms[j] != 'a' && perms[0] == '-') 1437 { 1438 err = 1; 1439 *xerrmsg = xstrdup ("user does not have all " 1440 "('a') permission"); 1441 } 1442 } 1443 if (perms[0] == '+') 1444 { 1445 fperms = xstrdup ("a"); 1446 fperms_len = strlen (fperms); 1447 } 1448 else if (perms[0] == '-') 1449 { 1450 fperms_len = 1; 1451 fperms = xmalloc (fperms_len); 1452 fperms[0] = '\0'; 1453 } 1454 break; 1455 case 'r': 1456 for (i = 0; i < fperms_len; i++) 1457 { 1458 if (fperms[i] == 'n' && perms[0] == '+') 1459 { 1460 fperms = xstrdup ("r"); 1461 fperms_len = strlen (fperms); 1462 } 1463 else if (fperms[i] == 'r' && perms[0] == '-') 1464 { 1465 fperms_len = 1; 1466 fperms = xmalloc (fperms_len); 1467 fperms[0] = '\0'; 1468 } 1469 else if (perms[0] == '-') 1470 { 1471 err = 1; 1472 *xerrmsg = xstrdup ("user has other permissions," 1473 " cannot remove read ('r')" 1474 " permission"); 1475 } 1476 else 1477 { 1478 err = 1; 1479 *xerrmsg = xstrdup ("user has other permissions," 1480 " cannot remove read ('r')" 1481 " permission"); 1482 } 1483 } 1484 break; 1485 case 'w': 1486 { 1487 tempfperms_len = 1; 1488 1489 tempfperms = xmalloc (tempfperms_len); 1490 tempfperms[0] = '\0'; 1491 1492 for (j = 0; j < fperms_len; j++) 1493 { 1494 if (fperms[j] == 't' || fperms[j] == 'c' || 1495 fperms[j] == 'd') 1496 { 1497 char *temp; 1498 temp = xmalloc (2); 1499 temp[0] = fperms[j]; 1500 temp[1] = '\0'; 1501 1502 xrealloc_and_strcat (&tempfperms, 1503 &tempfperms_len, temp); 1504 free (temp); 1505 } 1506 else if (fperms[j] == 'a' || fperms[j] == 'p') 1507 { 1508 err = 1; 1509 *xerrmsg = xstrdup ("user has higher" 1510 " permissions, cannot use" 1511 " +/- write permissions"); 1512 } 1513 else if (fperms[j] == 'n' || fperms[j] == 'r') 1514 { 1515 if (perms[0] == '-') 1516 { 1517 err = 1; 1518 *xerrmsg = xstrdup ("user does not have" 1519 " write ('w')" 1520 " permission"); 1521 } 1522 } 1523 else if (fperms[j] == 'w') 1524 { 1525 per = 1; 1526 if (perms[0] == '+') { 1527 err = 1; 1528 *xerrmsg = xstrdup ("user already have" 1529 " write ('w')" 1530 "permission"); 1531 } 1532 } 1533 } 1534 1535 fperms = tempfperms; 1536 fperms_len = strlen (fperms); 1537 1538 if (!per && !err && (perms[0] == '-')) { 1539 err = 1; 1540 *xerrmsg = xstrdup ("user does not have write" 1541 " ('w') permission"); 1542 } 1543 1544 if (perms[0] == '+') 1545 { 1546 xrealloc_and_strcat (&fperms, &fperms_len, "w"); 1547 } 1548 } 1549 break; 1550 case 't': 1551 { 1552 tempfperms_len = 1; 1553 1554 tempfperms = xmalloc (tempfperms_len); 1555 tempfperms[0] = '\0'; 1556 1557 for (j = 0; j < fperms_len; j++) 1558 { 1559 if (fperms[j] == 'w' || fperms[j] == 'c' || 1560 fperms[j] == 'd') 1561 { 1562 char *temp; 1563 temp = xmalloc (2); 1564 temp[0] = fperms[j]; 1565 temp[1] = '\0'; 1566 1567 xrealloc_and_strcat (&tempfperms, 1568 &tempfperms_len, temp); 1569 free (temp); 1570 } 1571 else if (fperms[j] == 'a' || fperms[j] == 'p') 1572 { 1573 err = 1; 1574 *xerrmsg = xstrdup ("user has higher" 1575 " permissions, cannot use" 1576 " +/- tag permissions"); 1577 } 1578 else if (fperms[j] == 'n' || fperms[i] == 'r') 1579 { 1580 if (perms[0] == '-') 1581 *xerrmsg = xstrdup ("user does not have tag" 1582 " ('t') permission"); 1583 } 1584 else if (fperms[j] == 't') 1585 { 1586 per = 1; 1587 if (perms[0] == '+') 1588 { 1589 err = 1; 1590 *xerrmsg = xstrdup ("user already have tag" 1591 " ('t') permission"); 1592 } 1593 } 1594 } 1595 1596 fperms = tempfperms; 1597 fperms_len = strlen (fperms); 1598 1599 if (!per && !err && (perms[0] == '-')) 1600 { 1601 err = 1; 1602 *xerrmsg = xstrdup ("user does not have tag ('t')" 1603 " permission"); 1604 } 1605 1606 if (perms[0] == '+') 1607 { 1608 xrealloc_and_strcat (&fperms, &fperms_len, "t"); 1609 } 1610 } 1611 break; 1612 case 'c': 1613 { 1614 tempfperms_len = 1; 1615 1616 tempfperms = xmalloc (tempfperms_len); 1617 tempfperms[0] = '\0'; 1618 1619 for (j = 0; j < fperms_len; j++) 1620 { 1621 if (fperms[j] == 'w' || fperms[j] == 't' || 1622 fperms[j] == 'd') 1623 { 1624 char *temp; 1625 temp = xmalloc (2); 1626 temp[0] = fperms[j]; 1627 temp[1] = '\0'; 1628 1629 xrealloc_and_strcat (&tempfperms, 1630 &tempfperms_len, temp); 1631 free (temp); 1632 } 1633 else if (fperms[j] == 'a' || fperms[j] == 'p') 1634 { 1635 err = 1; 1636 *xerrmsg = xstrdup ("user has higher" 1637 " permissions, cannot use" 1638 " +/- create permissions"); 1639 } 1640 else if (fperms[j] == 'n' || fperms[i] == 'r') 1641 { 1642 if (perms[0] == '-') 1643 err = 1; 1644 *xerrmsg = xstrdup ("user does not have create" 1645 " ('c') permission"); 1646 } 1647 else if (fperms[j] == 'c') 1648 { 1649 per = 1; 1650 if (perms[0] == '+') { 1651 err = 1; 1652 *xerrmsg = xstrdup ("user already have" 1653 " create ('c')" 1654 " permission"); 1655 } 1656 } 1657 } 1658 1659 fperms = tempfperms; 1660 fperms_len = strlen (fperms); 1661 1662 if (!per && !err && (perms[0] == '-')) { 1663 err = 1; 1664 *xerrmsg = xstrdup ("user does not have create" 1665 " ('c') permission"); 1666 } 1667 1668 if (perms[0] == '+') 1669 { 1670 xrealloc_and_strcat (&fperms, &fperms_len, "c"); 1671 } 1672 } 1673 break; 1674 case 'd': 1675 { 1676 tempfperms_len = 1; 1677 1678 tempfperms = xmalloc (tempfperms_len); 1679 tempfperms[0] = '\0'; 1680 1681 for (j = 0; j < fperms_len; j++) 1682 { 1683 if (fperms[j] == 'w' || fperms[j] == 'c' || 1684 fperms[j] == 't') 1685 { 1686 char *temp; 1687 temp = xmalloc (2); 1688 temp[0] = fperms[j]; 1689 temp[1] = '\0'; 1690 1691 xrealloc_and_strcat (&tempfperms, 1692 &tempfperms_len, temp); 1693 free (temp); 1694 } 1695 else if (fperms[j] == 'a' || fperms[j] == 'p') 1696 { 1697 err = 1; 1698 *xerrmsg = xstrdup ("user has higher" 1699 " permissions, cannot use" 1700 " +/- delete permissions"); 1701 } 1702 else if (fperms[j] == 'n' || fperms[i] == 'r') 1703 { 1704 if (perms[0] == '-') 1705 err = 1; 1706 *xerrmsg = xstrdup ("user does not have delete" 1707 " ('d') permission"); 1708 } 1709 else if (fperms[j] == 'd') 1710 { 1711 per = 1; 1712 if (perms[0] == '+') { 1713 err = 1; 1714 *xerrmsg = xstrdup ("user already have" 1715 " delete ('d')" 1716 " permission"); 1717 } 1718 } 1719 } 1720 1721 fperms = tempfperms; 1722 fperms_len = strlen (fperms); 1723 1724 if (!per && !err && (perms[0] == '-')) { 1725 err = 1; 1726 *xerrmsg = xstrdup ("user does not have delete" 1727 " ('d') permission"); 1728 } 1729 1730 if (perms[0] == '+') 1731 { 1732 xrealloc_and_strcat (&fperms, &fperms_len, "d"); 1733 } 1734 } 1735 break; 1736 default: 1737 err = 1; 1738 *xerrmsg = xstrdup ("error in 'access' file format"); 1739 break; 1740 } 1741 1742 if (fperms[0] == '\0') 1743 retperms = xstrdup ("none"); 1744 else 1745 retperms = xstrdup (fperms); 1746 } 1747 } 1748 else 1749 { 1750 err = 1; 1751 *xerrmsg = xstrdup("user is not given any permissions to remove/add"); 1752 } 1753 } 1754 else 1755 { 1756 retperms = xstrdup (perms); 1757 } 1758 if (fperms) 1759 free (fperms); 1760 if (err && retperms) 1761 free (retperms); 1762 1763 return (err ? NULL : retperms); 1764 } 1765 1766 /* prepare and write resulting permissions to access file */ 1767 static int 1768 write_perms (const char *user, const char *perms, const char *founduserpart, 1769 int foundline, char *otheruserparts, 1770 const char *part_type, const char *part_object, 1771 const char *part_tag, int pos, const char *arepos) 1772 { 1773 char *accessfile; 1774 char *tmpaccessout; 1775 FILE *accessfpin; 1776 FILE *accessfpout; 1777 1778 char *newline = NULL; 1779 size_t newlinelen = 1; 1780 char *object; 1781 1782 char *line = NULL; 1783 size_t line_allocated = 0; 1784 1785 newline = xmalloc (newlinelen); 1786 newline[0] = '\0'; 1787 1788 if (!strcasecmp (part_tag, "ALL")) 1789 part_tag = "ALL"; 1790 1791 /* strip any trailing slash if found */ 1792 object = xstrdup (part_object); 1793 if (object[strlen (object) - 1] == '/') 1794 object[strlen (object) - 1] = '\0'; 1795 1796 /* first parts, part type, object, and tag */ 1797 xrealloc_and_strcat (&newline, &newlinelen, part_type); 1798 xrealloc_and_strcat (&newline, &newlinelen, ":"); 1799 xrealloc_and_strcat (&newline, &newlinelen, object); 1800 xrealloc_and_strcat (&newline, &newlinelen, ":"); 1801 xrealloc_and_strcat (&newline, &newlinelen, part_tag); 1802 xrealloc_and_strcat (&newline, &newlinelen, ":"); 1803 1804 if (strncmp (perms, "none", 4) != 0) 1805 { 1806 xrealloc_and_strcat (&newline, &newlinelen, user); 1807 xrealloc_and_strcat (&newline, &newlinelen, "!"); 1808 xrealloc_and_strcat (&newline, &newlinelen, perms); 1809 if (otheruserparts != NULL) 1810 xrealloc_and_strcat (&newline, &newlinelen, ","); 1811 } 1812 1813 if (otheruserparts != NULL) 1814 { 1815 if (otheruserparts[strlen (otheruserparts) - 1] == '\n') 1816 otheruserparts[strlen (otheruserparts) - 1] = '\0'; 1817 1818 xrealloc_and_strcat (&newline, &newlinelen, otheruserparts); 1819 } 1820 1821 xrealloc_and_strcat (&newline, &newlinelen, ":"); 1822 1823 if (foundline) 1824 { 1825 accessfpout = cvs_temp_file (&tmpaccessout); 1826 if (accessfpout == NULL) 1827 error (1, errno, "cannot open temporary file: %s", tmpaccessout); 1828 1829 accessfpin = open_accessfile ("r", arepos, &accessfile); 1830 if (accessfpout == NULL) 1831 error (1, errno, "cannot open access file: %s", accessfile); 1832 1833 while (getline (&line, &line_allocated, accessfpin) >= 0) 1834 { 1835 if (pos != ftell (accessfpin)) 1836 { 1837 if (fprintf (accessfpout, "%s", line) < 0) 1838 error (1, errno, "writing temporary file: %s", tmpaccessout); 1839 } 1840 else 1841 { 1842 if (fprintf (accessfpout, "%s\n", newline) < 0) 1843 error (1, errno, "writing temporary file: %s", tmpaccessout); 1844 } 1845 1846 } 1847 if (fclose (accessfpin) == EOF) 1848 error (1, errno, "cannot close access file: %s", accessfile); 1849 1850 if (fclose (accessfpout) == EOF) 1851 error (1, errno, "cannot close temporary file: %s", tmpaccessout); 1852 1853 if (CVS_UNLINK (accessfile) < 0) 1854 error (0, errno, "cannot remove %s", accessfile); 1855 1856 copy_file (tmpaccessout, accessfile); 1857 1858 if (CVS_UNLINK (tmpaccessout) < 0) 1859 error (0, errno, "cannot remove temporary file: %s", tmpaccessout); 1860 } 1861 else 1862 { 1863 accessfpout = open_accessfile ("r+", arepos, &accessfile); 1864 1865 if (accessfpout == NULL) 1866 { 1867 if (existence_error (errno)) 1868 { 1869 accessfpout = open_accessfile ("w+", arepos, &accessfile); 1870 } 1871 if (accessfpout == NULL) 1872 error (1, errno, "cannot open access file: %s", accessfile); 1873 } 1874 else { 1875 if (fseek (accessfpout, 0, 2) != 0) 1876 error (1, errno, "cannot fseek access file: %s", accessfile); 1877 } 1878 1879 if (fprintf (accessfpout, "%s\n", newline) < 0) 1880 error (1, errno, "writing access file: %s", accessfile); 1881 1882 if (fclose (accessfpout) == EOF) 1883 error (1, errno, "cannot close access file: %s", accessfile); 1884 } 1885 1886 free (line); 1887 free (newline); 1888 1889 chmod (accessfile, 0644); 1890 1891 return 0; 1892 } 1893 1894 static int 1895 acllist_fileproc (void *callerdat, struct file_info *finfo) 1896 { 1897 char *filefullname; 1898 const char *frepository; 1899 char *line = NULL; 1900 int pos; 1901 1902 if (!aclfile) 1903 return 0; 1904 1905 frepository = Short_Repository (finfo->repository); 1906 1907 filefullname = Xasprintf("%s/%s", frepository, finfo->file); 1908 1909 /* check that user, which run acl/racl command, has admin permisson, 1910 * and also return the line with permissions from access file. */ 1911 if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos, 1912 0)) 1913 error (1, 0, "You do not have admin rights on '%s'", frepository); 1914 1915 acllist_print (line, filefullname); 1916 1917 free (filefullname); 1918 1919 return 0; 1920 } 1921 1922 static Dtype 1923 acllist_dirproc (void *callerdat, const char *dir, const char *repos, 1924 const char *update_dir, List *entries) 1925 { 1926 char *line = NULL; 1927 const char *drepository; 1928 int pos; 1929 1930 if (repos[0] == '\0') 1931 repos = Name_Repository (dir, NULL); 1932 1933 if (!acldir) 1934 return 0; 1935 1936 drepository = Short_Repository (repos); 1937 1938 /* check that user, which run acl/racl command, has admin permisson, 1939 * and also return the line with permissions from access file. */ 1940 if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0)) 1941 error (1, 0, "You do not have admin rights on '%s'", drepository); 1942 1943 acllist_print (line, drepository); 1944 1945 return 0; 1946 } 1947 1948 /* Prints permissions to screen with -l option */ 1949 void 1950 acllist_print (char *line, const char *obj) 1951 { 1952 char *temp; 1953 int c = 0; 1954 int def = 0; 1955 1956 char *printedusers[255]; 1957 printedusers[0] = NULL; 1958 1959 if (line != NULL) 1960 { 1961 temp = strtok (line, ":\t"); 1962 1963 if (acldir) 1964 cvs_output ("d ", 0); 1965 else if (aclfile) 1966 cvs_output ("f ", 0); 1967 1968 temp = strtok (NULL, ":\t"); 1969 1970 cvs_output(obj, 0); 1971 cvs_output (" | ", 0); 1972 1973 temp = strtok (NULL, ":\t"); 1974 cvs_output (temp, 0); 1975 cvs_output (" | ", 0); 1976 1977 while ((temp = strtok (NULL, "!\t")) != NULL) 1978 { 1979 if (strncmp (temp, ":", 1) == 0) 1980 break; 1981 1982 if (strcmp (temp, "ALL") == 0) 1983 { 1984 temp = strtok (NULL, ",\t"); 1985 continue; 1986 } 1987 1988 cvs_output (temp, 0); 1989 cvs_output (":", 0); 1990 1991 while (printedusers[c] != NULL) 1992 c++; 1993 1994 printedusers[c] = xstrdup (temp); 1995 c++; 1996 printedusers[c] = NULL; 1997 1998 temp = strtok (NULL, ",\t"); 1999 2000 if (temp != NULL && temp[strlen (temp) - 2] == ':') 2001 temp[strlen (temp) - 2] = '\0'; 2002 2003 cvs_output (temp, 0); 2004 cvs_output (" ", 0); 2005 } 2006 2007 if (default_perms_object) 2008 { 2009 cvs_output ("| defaults ", 0); 2010 cvs_output ("ALL:", 0); 2011 cvs_output (default_perms_object, 0); 2012 def = 1; 2013 } 2014 if (default_part_perms_accessfile) 2015 { 2016 size_t i; 2017 i = strlen (default_part_perms_accessfile); 2018 xrealloc_and_strcat (&default_part_perms_accessfile, &i, ","); 2019 2020 free (line); 2021 line = xstrdup (default_part_perms_accessfile); 2022 2023 if (!def) 2024 cvs_output ("| defaults ", 0); 2025 else 2026 cvs_output (" ", 0); 2027 2028 temp = strtok (line, "!\t"); 2029 cvs_output (temp, 0); 2030 cvs_output (":", 0); 2031 2032 temp = strtok (NULL, ",\t"); 2033 2034 cvs_output (temp, 0); 2035 cvs_output (" ", 0); 2036 2037 while ((temp = strtok (NULL, "!\t")) != NULL) 2038 { 2039 int printed = 0; 2040 int c2 = 0; 2041 while (printedusers[c2] != NULL && printed == 0) 2042 { 2043 if (strcmp (printedusers[c2], temp) == 0) 2044 { 2045 printed = 1; 2046 break; 2047 } 2048 c2++; 2049 } 2050 2051 if (printed == 0) 2052 { 2053 cvs_output (temp, 0); 2054 cvs_output (":", 0); 2055 } 2056 2057 temp = strtok (NULL, ",\t"); 2058 2059 if (temp[strlen (temp) - 2] == ':') 2060 temp[strlen (temp) - 2] = '\0'; 2061 2062 if (printed == 0) 2063 { 2064 cvs_output (temp, 0); 2065 cvs_output (" ", 0); 2066 } 2067 } 2068 def = 1; 2069 } 2070 else if (cvs_acl_default_permissions) 2071 { 2072 cvs_output ("| defaults ", 0); 2073 cvs_output ("ALL: ", 0); 2074 cvs_output (cvs_acl_default_permissions, 0); 2075 } 2076 } 2077 else 2078 { 2079 if (acldir) 2080 cvs_output ("d ", 0); 2081 else if (aclfile) 2082 cvs_output ("f ", 0); 2083 cvs_output (obj, 0); 2084 cvs_output (" | ", 0); 2085 cvs_output (tag, 0); 2086 cvs_output (" | ", 0); 2087 2088 if (default_perms_object) 2089 { 2090 cvs_output ("| defaults ", 0); 2091 cvs_output ("ALL:", 0); 2092 cvs_output (default_perms_object, 0); 2093 def = 1; 2094 } 2095 if (default_part_perms_accessfile) 2096 { 2097 free (line); 2098 line = xstrdup (default_part_perms_accessfile); 2099 2100 if (!def) 2101 cvs_output ("| defaults ", 0); 2102 else 2103 cvs_output (" ", 0); 2104 2105 temp = strtok (line, "!\t"); 2106 cvs_output (temp, 0); 2107 cvs_output (":", 0); 2108 2109 temp = strtok (NULL, ",\t"); 2110 2111 if (temp[strlen (temp) - 2] == ':') 2112 temp[strlen (temp) - 2] = '\0'; 2113 2114 cvs_output (temp, 0); 2115 cvs_output (" ", 0); 2116 2117 while ((temp = strtok (NULL, "!\t")) != NULL) 2118 { 2119 cvs_output (temp, 0); 2120 cvs_output (":", 0); 2121 2122 if ((temp = strtok (NULL, ",\t")) != NULL) 2123 { 2124 if (temp[strlen (temp) - 2] == ':') 2125 temp[strlen (temp) - 2] = '\0'; 2126 2127 cvs_output (temp, 0); 2128 cvs_output (" ", 0); 2129 } 2130 } 2131 cvs_output ("\n", 0); 2132 } 2133 else if (cvs_acl_default_permissions) 2134 { 2135 cvs_output ("| defaults ", 0); 2136 cvs_output ("ALL: ", 0); 2137 cvs_output (cvs_acl_default_permissions, 0); 2138 } 2139 else 2140 cvs_output ("default:p (no perms)", 0); 2141 } 2142 cvs_output ("\n", 0); 2143 2144 while (c >= 0) { 2145 free (printedusers[c]); 2146 c--; 2147 } 2148 2149 free (line); 2150 } 2151 2152 /* find username 2153 * returns username with its permissions if user found 2154 * returns NULL if user not found */ 2155 char *findusername (const char *string1, const char *string2) 2156 { 2157 char *tmp1, *tmp2; 2158 2159 if (string1 != NULL && string2 != NULL) 2160 { 2161 tmp1 = xstrdup (string1); 2162 tmp2 = strtok (tmp1, ",\t"); 2163 2164 do 2165 { 2166 if (strncmp (tmp2, string2, strlen (string2)) == 0 && 2167 tmp2[strlen (string2)] == '!') 2168 { 2169 tmp2 = xstrdup (tmp2); 2170 free (tmp1); 2171 return tmp2; 2172 } 2173 tmp2 = strtok (NULL, ",\t"); 2174 } 2175 while (tmp2 != NULL); 2176 2177 free (tmp1); 2178 2179 return NULL; 2180 } 2181 else 2182 return NULL; 2183 } 2184 2185 /* find user name in group file 2186 * returns group name if user found 2187 * returns NULL if user not found */ 2188 char *findgroupname (const char *string1, const char *string2) 2189 { 2190 char *tmp1, *tmp2; 2191 char *grpname; 2192 2193 if (string1 != NULL && string2 != NULL) 2194 { 2195 tmp1 = xstrdup (string1); 2196 grpname = strtok (tmp1, ":\t"); 2197 2198 while (tmp2 = strtok(NULL, ",\t")) 2199 { 2200 if (strcmp (tmp2, string2) == 0) 2201 { 2202 grpname = xstrdup (grpname); 2203 free (tmp1); 2204 return grpname; 2205 } 2206 } 2207 2208 free (tmp1); 2209 2210 return NULL; 2211 } 2212 else 2213 return NULL; 2214 } 2215