summaryrefslogtreecommitdiff
path: root/debian/patches/user-group-modes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/user-group-modes.patch')
-rw-r--r--debian/patches/user-group-modes.patch202
1 files changed, 202 insertions, 0 deletions
diff --git a/debian/patches/user-group-modes.patch b/debian/patches/user-group-modes.patch
new file mode 100644
index 000000000..ddedbf79a
--- /dev/null
+++ b/debian/patches/user-group-modes.patch
@@ -0,0 +1,202 @@
1Description: Allow harmless group-writability
2 Allow secure files (~/.ssh/config, ~/.ssh/authorized_keys, etc.) to be
3 group-writable, provided that the group in question contains only the
4 file's owner. Rejected upstream for IMO incorrect reasons (e.g. a
5 misunderstanding about the contents of gr->gr_mem). Given that
6 per-user groups and umask 002 are the default setup in Debian (for good
7 reasons - this makes operating in setgid directories with other groups
8 much easier), we need to permit this by default.
9Author: Colin Watson <cjwatson@debian.org>
10Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1060
11Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=314347
12Last-Update: 2013-05-07
13
14Index: b/readconf.c
15===================================================================
16--- a/readconf.c
17+++ b/readconf.c
18@@ -30,6 +30,8 @@
19 #include <stdio.h>
20 #include <string.h>
21 #include <unistd.h>
22+#include <pwd.h>
23+#include <grp.h>
24
25 #include "xmalloc.h"
26 #include "ssh.h"
27@@ -1132,8 +1134,7 @@
28
29 if (fstat(fileno(f), &sb) == -1)
30 fatal("fstat %s: %s", filename, strerror(errno));
31- if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
32- (sb.st_mode & 022) != 0))
33+ if (!secure_permissions(&sb, getuid()))
34 fatal("Bad owner or permissions on %s", filename);
35 }
36
37Index: b/ssh.1
38===================================================================
39--- a/ssh.1
40+++ b/ssh.1
41@@ -1320,6 +1320,8 @@
42 .Xr ssh_config 5 .
43 Because of the potential for abuse, this file must have strict permissions:
44 read/write for the user, and not accessible by others.
45+It may be group-writable provided that the group in question contains only
46+the user.
47 .Pp
48 .It Pa ~/.ssh/environment
49 Contains additional definitions for environment variables; see
50Index: b/ssh_config.5
51===================================================================
52--- a/ssh_config.5
53+++ b/ssh_config.5
54@@ -1356,6 +1356,8 @@
55 This file is used by the SSH client.
56 Because of the potential for abuse, this file must have strict permissions:
57 read/write for the user, and not accessible by others.
58+It may be group-writable provided that the group in question contains only
59+the user.
60 .It Pa /etc/ssh/ssh_config
61 Systemwide configuration file.
62 This file provides defaults for those
63Index: b/auth.c
64===================================================================
65--- a/auth.c
66+++ b/auth.c
67@@ -386,8 +386,7 @@
68 user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
69 if (options.strict_modes &&
70 (stat(user_hostfile, &st) == 0) &&
71- ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
72- (st.st_mode & 022) != 0)) {
73+ !secure_permissions(&st, pw->pw_uid)) {
74 logit("Authentication refused for %.100s: "
75 "bad owner or modes for %.200s",
76 pw->pw_name, user_hostfile);
77@@ -449,8 +448,7 @@
78 snprintf(err, errlen, "%s is not a regular file", buf);
79 return -1;
80 }
81- if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
82- (stp->st_mode & 022) != 0) {
83+ if (!secure_permissions(stp, uid)) {
84 snprintf(err, errlen, "bad ownership or modes for file %s",
85 buf);
86 return -1;
87@@ -465,8 +463,7 @@
88 strlcpy(buf, cp, sizeof(buf));
89
90 if (stat(buf, &st) < 0 ||
91- (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
92- (st.st_mode & 022) != 0) {
93+ !secure_permissions(&st, uid)) {
94 snprintf(err, errlen,
95 "bad ownership or modes for directory %s", buf);
96 return -1;
97Index: b/misc.c
98===================================================================
99--- a/misc.c
100+++ b/misc.c
101@@ -48,8 +48,9 @@
102 #include <netdb.h>
103 #ifdef HAVE_PATHS_H
104 # include <paths.h>
105-#include <pwd.h>
106 #endif
107+#include <pwd.h>
108+#include <grp.h>
109 #ifdef SSH_TUN_OPENBSD
110 #include <net/if.h>
111 #endif
112@@ -642,6 +643,55 @@
113 }
114
115 int
116+secure_permissions(struct stat *st, uid_t uid)
117+{
118+ if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid)
119+ return 0;
120+ if ((st->st_mode & 002) != 0)
121+ return 0;
122+ if ((st->st_mode & 020) != 0) {
123+ /* If the file is group-writable, the group in question must
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.)
127+ */
128+ struct passwd *pw;
129+ struct group *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)
148+ return 0;
149+
150+ /* Check supplementary group memberships. */
151+ if (gr->gr_mem[0]) {
152+ ++members;
153+ if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
154+ gr->gr_mem[1])
155+ return 0;
156+ }
157+
158+ if (!members)
159+ return 0;
160+ }
161+ return 1;
162+}
163+
164+int
165 tun_open(int tun, int mode)
166 {
167 #if defined(CUSTOM_SYS_TUN_OPEN)
168Index: b/misc.h
169===================================================================
170--- a/misc.h
171+++ b/misc.h
172@@ -103,4 +103,6 @@
173 int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
174 int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
175
176+int secure_permissions(struct stat *st, uid_t uid);
177+
178 #endif /* _MISC_H */
179Index: b/auth-rhosts.c
180===================================================================
181--- a/auth-rhosts.c
182+++ b/auth-rhosts.c
183@@ -256,8 +256,7 @@
184 return 0;
185 }
186 if (options.strict_modes &&
187- ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
188- (st.st_mode & 022) != 0)) {
189+ !secure_permissions(&st, pw->pw_uid)) {
190 logit("Rhosts authentication refused for %.100s: "
191 "bad ownership or modes for home directory.", pw->pw_name);
192 auth_debug_add("Rhosts authentication refused for %.100s: "
193@@ -283,8 +282,7 @@
194 * allowing access to their account by anyone.
195 */
196 if (options.strict_modes &&
197- ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
198- (st.st_mode & 022) != 0)) {
199+ !secure_permissions(&st, pw->pw_uid)) {
200 logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
201 pw->pw_name, buf);
202 auth_debug_add("Bad file modes for %.200s", buf);