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