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.patch259
1 files changed, 259 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..e08b6c7b7
--- /dev/null
+++ b/debian/patches/user-group-modes.patch
@@ -0,0 +1,259 @@
1From df060c830ad66289a93be24268f3f70e7021be29 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:09:58 +0000
4Subject: Allow harmless group-writability
5
6Allow secure files (~/.ssh/config, ~/.ssh/authorized_keys, etc.) to be
7group-writable, provided that the group in question contains only the file's
8owner. Rejected upstream for IMO incorrect reasons (e.g. a misunderstanding
9about the contents of gr->gr_mem). Given that per-user groups and umask 002
10are the default setup in Debian (for good reasons - this makes operating in
11setgid directories with other groups much easier), we need to permit this by
12default.
13
14Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1060
15Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=314347
16Last-Update: 2013-09-14
17
18Patch-Name: user-group-modes.patch
19---
20 auth-rhosts.c | 6 ++----
21 auth.c | 9 +++-----
22 misc.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
23 misc.h | 2 ++
24 platform.c | 16 --------------
25 readconf.c | 3 +--
26 ssh.1 | 2 ++
27 ssh_config.5 | 2 ++
28 8 files changed, 80 insertions(+), 29 deletions(-)
29
30diff --git a/auth-rhosts.c b/auth-rhosts.c
31index ecf956f0..4dccd5e6 100644
32--- a/auth-rhosts.c
33+++ b/auth-rhosts.c
34@@ -261,8 +261,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
35 return 0;
36 }
37 if (options.strict_modes &&
38- ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
39- (st.st_mode & 022) != 0)) {
40+ !secure_permissions(&st, pw->pw_uid)) {
41 logit("Rhosts authentication refused for %.100s: "
42 "bad ownership or modes for home directory.", pw->pw_name);
43 auth_debug_add("Rhosts authentication refused for %.100s: "
44@@ -288,8 +287,7 @@ auth_rhosts2(struct passwd *pw, const char *client_user, const char *hostname,
45 * allowing access to their account by anyone.
46 */
47 if (options.strict_modes &&
48- ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
49- (st.st_mode & 022) != 0)) {
50+ !secure_permissions(&st, pw->pw_uid)) {
51 logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
52 pw->pw_name, buf);
53 auth_debug_add("Bad file modes for %.200s", buf);
54diff --git a/auth.c b/auth.c
55index c6390687..90390724 100644
56--- a/auth.c
57+++ b/auth.c
58@@ -444,8 +444,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
59 user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
60 if (options.strict_modes &&
61 (stat(user_hostfile, &st) == 0) &&
62- ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
63- (st.st_mode & 022) != 0)) {
64+ !secure_permissions(&st, pw->pw_uid)) {
65 logit("Authentication refused for %.100s: "
66 "bad owner or modes for %.200s",
67 pw->pw_name, user_hostfile);
68@@ -507,8 +506,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
69 snprintf(err, errlen, "%s is not a regular file", buf);
70 return -1;
71 }
72- if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) ||
73- (stp->st_mode & 022) != 0) {
74+ if (!secure_permissions(stp, uid)) {
75 snprintf(err, errlen, "bad ownership or modes for file %s",
76 buf);
77 return -1;
78@@ -523,8 +521,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
79 strlcpy(buf, cp, sizeof(buf));
80
81 if (stat(buf, &st) < 0 ||
82- (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) ||
83- (st.st_mode & 022) != 0) {
84+ !secure_permissions(&st, uid)) {
85 snprintf(err, errlen,
86 "bad ownership or modes for directory %s", buf);
87 return -1;
88diff --git a/misc.c b/misc.c
89index 65c9222a..bf9153a6 100644
90--- a/misc.c
91+++ b/misc.c
92@@ -51,8 +51,9 @@
93 #include <netdb.h>
94 #ifdef HAVE_PATHS_H
95 # include <paths.h>
96-#include <pwd.h>
97 #endif
98+#include <pwd.h>
99+#include <grp.h>
100 #ifdef SSH_TUN_OPENBSD
101 #include <net/if.h>
102 #endif
103@@ -61,6 +62,7 @@
104 #include "misc.h"
105 #include "log.h"
106 #include "ssh.h"
107+#include "platform.h"
108
109 /* remove newline at end of string */
110 char *
111@@ -708,6 +710,71 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
112 return -1;
113 }
114
115+/*
116+ * return 1 if the specified uid is a uid that may own a system directory
117+ * otherwise 0.
118+ */
119+int
120+platform_sys_dir_uid(uid_t uid)
121+{
122+ if (uid == 0)
123+ return 1;
124+#ifdef PLATFORM_SYS_DIR_UID
125+ if (uid == PLATFORM_SYS_DIR_UID)
126+ return 1;
127+#endif
128+ return 0;
129+}
130+
131+int
132+secure_permissions(struct stat *st, uid_t uid)
133+{
134+ if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid)
135+ return 0;
136+ if ((st->st_mode & 002) != 0)
137+ return 0;
138+ if ((st->st_mode & 020) != 0) {
139+ /* If the file is group-writable, the group in question must
140+ * have exactly one member, namely the file's owner.
141+ * (Zero-member groups are typically used by setgid
142+ * binaries, and are unlikely to be suitable.)
143+ */
144+ struct passwd *pw;
145+ struct group *gr;
146+ int members = 0;
147+
148+ gr = getgrgid(st->st_gid);
149+ if (!gr)
150+ return 0;
151+
152+ /* Check primary group memberships. */
153+ while ((pw = getpwent()) != NULL) {
154+ if (pw->pw_gid == gr->gr_gid) {
155+ ++members;
156+ if (pw->pw_uid != uid)
157+ return 0;
158+ }
159+ }
160+ endpwent();
161+
162+ pw = getpwuid(st->st_uid);
163+ if (!pw)
164+ return 0;
165+
166+ /* Check supplementary group memberships. */
167+ if (gr->gr_mem[0]) {
168+ ++members;
169+ if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
170+ gr->gr_mem[1])
171+ return 0;
172+ }
173+
174+ if (!members)
175+ return 0;
176+ }
177+ return 1;
178+}
179+
180 int
181 tun_open(int tun, int mode)
182 {
183diff --git a/misc.h b/misc.h
184index c242f901..8b223b55 100644
185--- a/misc.h
186+++ b/misc.h
187@@ -143,6 +143,8 @@ char *read_passphrase(const char *, int);
188 int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
189 int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
190
191+int secure_permissions(struct stat *st, uid_t uid);
192+
193 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
194 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
195 #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
196diff --git a/platform.c b/platform.c
197index cd7bf566..380ee3a4 100644
198--- a/platform.c
199+++ b/platform.c
200@@ -197,19 +197,3 @@ platform_krb5_get_principal_name(const char *pw_name)
201 return NULL;
202 #endif
203 }
204-
205-/*
206- * return 1 if the specified uid is a uid that may own a system directory
207- * otherwise 0.
208- */
209-int
210-platform_sys_dir_uid(uid_t uid)
211-{
212- if (uid == 0)
213- return 1;
214-#ifdef PLATFORM_SYS_DIR_UID
215- if (uid == PLATFORM_SYS_DIR_UID)
216- return 1;
217-#endif
218- return 0;
219-}
220diff --git a/readconf.c b/readconf.c
221index 3efba242..c02cdf63 100644
222--- a/readconf.c
223+++ b/readconf.c
224@@ -1752,8 +1752,7 @@ read_config_file_depth(const char *filename, struct passwd *pw,
225
226 if (fstat(fileno(f), &sb) == -1)
227 fatal("fstat %s: %s", filename, strerror(errno));
228- if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
229- (sb.st_mode & 022) != 0))
230+ if (!secure_permissions(&sb, getuid()))
231 fatal("Bad owner or permissions on %s", filename);
232 }
233
234diff --git a/ssh.1 b/ssh.1
235index 4011c65a..feef81a5 100644
236--- a/ssh.1
237+++ b/ssh.1
238@@ -1484,6 +1484,8 @@ The file format and configuration options are described in
239 .Xr ssh_config 5 .
240 Because of the potential for abuse, this file must have strict permissions:
241 read/write for the user, and not writable by others.
242+It may be group-writable provided that the group in question contains only
243+the user.
244 .Pp
245 .It Pa ~/.ssh/environment
246 Contains additional definitions for environment variables; see
247diff --git a/ssh_config.5 b/ssh_config.5
248index 32fd100d..f62ea6b8 100644
249--- a/ssh_config.5
250+++ b/ssh_config.5
251@@ -1803,6 +1803,8 @@ The format of this file is described above.
252 This file is used by the SSH client.
253 Because of the potential for abuse, this file must have strict permissions:
254 read/write for the user, and not accessible by others.
255+It may be group-writable provided that the group in question contains only
256+the user.
257 .It Pa /etc/ssh/ssh_config
258 Systemwide configuration file.
259 This file provides defaults for those