summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-05-22 23:37:08 +0100
committerColin Watson <cjwatson@debian.org>2010-05-22 23:37:08 +0100
commitfd8ccdb64c4b65092d8bac720e17068e5ef31881 (patch)
treebd019e95cdebce817daeec5403d64ebb13b58dfb
parentd61e316833eb7d05b0b5c937bfce8ee0f19dc7cb (diff)
Check primary group memberships as well as supplementary group
memberships, and only allow group-writability by groups with exactly one member, as zero-member groups are typically used by setgid binaries rather than being user-private groups (closes: #581697).
-rw-r--r--debian/changelog4
-rw-r--r--debian/patches/user-group-modes.patch41
-rw-r--r--misc.c39
3 files changed, 69 insertions, 15 deletions
diff --git a/debian/changelog b/debian/changelog
index a27f3b57f..60d985e2f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -9,6 +9,10 @@ openssh (1:5.5p1-4) UNRELEASED; urgency=low
9 group-writable, provided that the group in question contains only the 9 group-writable, provided that the group in question contains only the
10 file's owner; this extends a patch previously applied to ~/.ssh/config 10 file's owner; this extends a patch previously applied to ~/.ssh/config
11 (closes: #581919). 11 (closes: #581919).
12 * Check primary group memberships as well as supplementary group
13 memberships, and only allow group-writability by groups with exactly one
14 member, as zero-member groups are typically used by setgid binaries
15 rather than being user-private groups (closes: #581697).
12 16
13 -- Colin Watson <cjwatson@debian.org> Tue, 04 May 2010 13:32:17 +0100 17 -- Colin Watson <cjwatson@debian.org> Tue, 04 May 2010 13:32:17 +0100
14 18
diff --git a/debian/patches/user-group-modes.patch b/debian/patches/user-group-modes.patch
index 8cf862049..164b8ec81 100644
--- a/debian/patches/user-group-modes.patch
+++ b/debian/patches/user-group-modes.patch
@@ -109,7 +109,7 @@ Index: b/misc.c
109 #ifdef SSH_TUN_OPENBSD 109 #ifdef SSH_TUN_OPENBSD
110 #include <net/if.h> 110 #include <net/if.h>
111 #endif 111 #endif
112@@ -638,6 +639,30 @@ 112@@ -638,6 +639,55 @@
113 } 113 }
114 114
115 int 115 int
@@ -117,22 +117,47 @@ Index: b/misc.c
117+{ 117+{
118+ if (st->st_uid != 0 && st->st_uid != uid) 118+ if (st->st_uid != 0 && st->st_uid != uid)
119+ return 0; 119+ return 0;
120+ if ((st->st_mode & 002) != 0)
121+ return 0;
120+ if ((st->st_mode & 020) != 0) { 122+ if ((st->st_mode & 020) != 0) {
121+ /* If the file is group-writable, the group in question must 123+ /* If the file is group-writable, the group in question must
122+ * have at most one member, namely the file's owner. 124+ * have exactly one member, namely the file's owner.
125+ * (Zero-member groups are typically used by setgid
126+ * binaries, and are unlikely to be suitable.)
123+ */ 127+ */
124+ struct passwd *pw = getpwuid(st->st_uid); 128+ struct passwd *pw;
125+ struct group *gr = getgrgid(st->st_gid); 129+ struct group *gr;
126+ if (!pw || !gr) 130+ int members = 0;
131+
132+ gr = getgrgid(st->st_gid);
133+ if (!gr)
134+ return 0;
135+
136+ /* Check primary group memberships. */
137+ while ((pw = getpwent()) != NULL) {
138+ if (pw->pw_gid == gr->gr_gid) {
139+ ++members;
140+ if (pw->pw_uid != uid)
141+ return 0;
142+ }
143+ }
144+ endpwent();
145+
146+ pw = getpwuid(st->st_uid);
147+ if (!pw)
127+ return 0; 148+ return 0;
128+ else if (gr->gr_mem[0]) { 149+
150+ /* Check supplementary group memberships. */
151+ if (gr->gr_mem[0]) {
152+ ++members;
129+ if (strcmp(pw->pw_name, gr->gr_mem[0]) || 153+ if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
130+ gr->gr_mem[1]) 154+ gr->gr_mem[1])
131+ return 0; 155+ return 0;
132+ } 156+ }
157+
158+ if (!members)
159+ return 0;
133+ } 160+ }
134+ if ((st->st_mode & 002) != 0)
135+ return 0;
136+ return 1; 161+ return 1;
137+} 162+}
138+ 163+
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