summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c39
1 files changed, 32 insertions, 7 deletions
diff --git a/misc.c b/misc.c
index 4ca318423..f9da621d6 100644
--- a/misc.c
+++ b/misc.c
@@ -643,22 +643,47 @@ secure_permissions(struct stat *st, uid_t uid)
643{ 643{
644 if (st->st_uid != 0 && st->st_uid != uid) 644 if (st->st_uid != 0 && st->st_uid != uid)
645 return 0; 645 return 0;
646 if ((st->st_mode & 002) != 0)
647 return 0;
646 if ((st->st_mode & 020) != 0) { 648 if ((st->st_mode & 020) != 0) {
647 /* If the file is group-writable, the group in question must 649 /* If the file is group-writable, the group in question must
648 * have at most one member, namely the file's owner. 650 * have exactly one member, namely the file's owner.
651 * (Zero-member groups are typically used by setgid
652 * binaries, and are unlikely to be suitable.)
649 */ 653 */
650 struct passwd *pw = getpwuid(st->st_uid); 654 struct passwd *pw;
651 struct group *gr = getgrgid(st->st_gid); 655 struct group *gr;
652 if (!pw || !gr) 656 int members = 0;
657
658 gr = getgrgid(st->st_gid);
659 if (!gr)
653 return 0; 660 return 0;
654 else if (gr->gr_mem[0]) { 661
662 /* Check primary group memberships. */
663 while ((pw = getpwent()) != NULL) {
664 if (pw->pw_gid == gr->gr_gid) {
665 ++members;
666 if (pw->pw_uid != uid)
667 return 0;
668 }
669 }
670 endpwent();
671
672 pw = getpwuid(st->st_uid);
673 if (!pw)
674 return 0;
675
676 /* Check supplementary group memberships. */
677 if (gr->gr_mem[0]) {
678 ++members;
655 if (strcmp(pw->pw_name, gr->gr_mem[0]) || 679 if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
656 gr->gr_mem[1]) 680 gr->gr_mem[1])
657 return 0; 681 return 0;
658 } 682 }
683
684 if (!members)
685 return 0;
659 } 686 }
660 if ((st->st_mode & 002) != 0)
661 return 0;
662 return 1; 687 return 1;
663} 688}
664 689