summaryrefslogtreecommitdiff
path: root/debian/patches/user-group-modes.patch
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2010-05-22 22:43:47 +0100
committerColin Watson <cjwatson@debian.org>2010-05-22 22:43:47 +0100
commitd61e316833eb7d05b0b5c937bfce8ee0f19dc7cb (patch)
tree5a2e2057bd64ca0825d5edf13e55128a2fb7cadb /debian/patches/user-group-modes.patch
parentec9f6c25d67f48277fe2ed56fa7773c7f6cf3580 (diff)
Allow ~/.ssh/authorized_keys and other secure files to be
group-writable, provided that the group in question contains only the file's owner; this extends a patch previously applied to ~/.ssh/config (closes: #581919).
Diffstat (limited to 'debian/patches/user-group-modes.patch')
-rw-r--r--debian/patches/user-group-modes.patch155
1 files changed, 124 insertions, 31 deletions
diff --git a/debian/patches/user-group-modes.patch b/debian/patches/user-group-modes.patch
index 4d7ebe566..8cf862049 100644
--- a/debian/patches/user-group-modes.patch
+++ b/debian/patches/user-group-modes.patch
@@ -1,10 +1,11 @@
1Description: Allow harmless group-writability 1Description: Allow harmless group-writability
2 Allow ~/.ssh/config to be group-writable, provided that the group in 2 Allow secure files (~/.ssh/config, ~/.ssh/authorized_keys, etc.) to be
3 question contains only the file's owner. Rejected upstream for IMO 3 group-writable, provided that the group in question contains only the
4 incorrect reasons (e.g. a misunderstanding about the contents of 4 file's owner. Rejected upstream for IMO incorrect reasons (e.g. a
5 gr->gr_mem). Given that per-user groups and umask 002 are the default 5 misunderstanding about the contents of gr->gr_mem). Given that
6 setup in Debian (for good reasons - this makes operating in setgid 6 per-user groups and umask 002 are the default setup in Debian (for good
7 directories with other groups much easier), we need to permit this. 7 reasons - this makes operating in setgid directories with other groups
8 much easier), we need to permit this by default.
8Author: Colin Watson <cjwatson@debian.org> 9Author: Colin Watson <cjwatson@debian.org>
9Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1060 10Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1060
10Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=314347 11Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=314347
@@ -23,36 +24,13 @@ Index: b/readconf.c
23 24
24 #include "xmalloc.h" 25 #include "xmalloc.h"
25 #include "ssh.h" 26 #include "ssh.h"
26@@ -1000,11 +1002,30 @@ 27@@ -1003,8 +1005,7 @@
27
28 if (checkperm) {
29 struct stat sb;
30+ int bad_modes = 0;
31 28
32 if (fstat(fileno(f), &sb) == -1) 29 if (fstat(fileno(f), &sb) == -1)
33 fatal("fstat %s: %s", filename, strerror(errno)); 30 fatal("fstat %s: %s", filename, strerror(errno));
34- if (((sb.st_uid != 0 && sb.st_uid != getuid()) || 31- if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
35- (sb.st_mode & 022) != 0)) 32- (sb.st_mode & 022) != 0))
36+ if (sb.st_uid != 0 && sb.st_uid != getuid()) 33+ if (!secure_permissions(&sb, getuid()))
37+ bad_modes = 1;
38+ if ((sb.st_mode & 020) != 0) {
39+ /* If the file is group-writable, the group in
40+ * question must have at most one member, namely the
41+ * file's owner.
42+ */
43+ struct passwd *pw = getpwuid(sb.st_uid);
44+ struct group *gr = getgrgid(sb.st_gid);
45+ if (!pw || !gr)
46+ bad_modes = 1;
47+ else if (gr->gr_mem[0]) {
48+ if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
49+ gr->gr_mem[1])
50+ bad_modes = 1;
51+ }
52+ }
53+ if ((sb.st_mode & 002) != 0)
54+ bad_modes = 1;
55+ if (bad_modes)
56 fatal("Bad owner or permissions on %s", filename); 34 fatal("Bad owner or permissions on %s", filename);
57 } 35 }
58 36
@@ -82,3 +60,118 @@ Index: b/ssh_config.5
82 .It Pa /etc/ssh/ssh_config 60 .It Pa /etc/ssh/ssh_config
83 Systemwide configuration file. 61 Systemwide configuration file.
84 This file provides defaults for those 62 This file provides defaults for those
63Index: b/auth.c
64===================================================================
65--- a/auth.c
66+++ b/auth.c
67@@ -385,8 +385,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@@ -438,8 +437,7 @@
78
79 /* check the open file to avoid races */
80 if (fstat(fileno(f), &st) < 0 ||
81- (st.st_uid != 0 && st.st_uid != uid) ||
82- (st.st_mode & 022) != 0) {
83+ !secure_permissions(&st, uid)) {
84 snprintf(err, errlen, "bad ownership or modes for file %s",
85 buf);
86 return -1;
87@@ -455,8 +453,7 @@
88
89 debug3("secure_filename: checking '%s'", buf);
90 if (stat(buf, &st) < 0 ||
91- (st.st_uid != 0 && 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@@ -45,8 +45,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@@ -638,6 +639,30 @@
113 }
114
115 int
116+secure_permissions(struct stat *st, uid_t uid)
117+{
118+ if (st->st_uid != 0 && st->st_uid != uid)
119+ return 0;
120+ if ((st->st_mode & 020) != 0) {
121+ /* If the file is group-writable, the group in question must
122+ * have at most one member, namely the file's owner.
123+ */
124+ struct passwd *pw = getpwuid(st->st_uid);
125+ struct group *gr = getgrgid(st->st_gid);
126+ if (!pw || !gr)
127+ return 0;
128+ else if (gr->gr_mem[0]) {
129+ if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
130+ gr->gr_mem[1])
131+ return 0;
132+ }
133+ }
134+ if ((st->st_mode & 002) != 0)
135+ return 0;
136+ return 1;
137+}
138+
139+int
140 tun_open(int tun, int mode)
141 {
142 #if defined(CUSTOM_SYS_TUN_OPEN)
143Index: b/misc.h
144===================================================================
145--- a/misc.h
146+++ b/misc.h
147@@ -91,4 +91,6 @@
148 int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
149 int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
150
151+int secure_permissions(struct stat *st, uid_t uid);
152+
153 #endif /* _MISC_H */
154Index: b/auth-rhosts.c
155===================================================================
156--- a/auth-rhosts.c
157+++ b/auth-rhosts.c
158@@ -256,8 +256,7 @@
159 return 0;
160 }
161 if (options.strict_modes &&
162- ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
163- (st.st_mode & 022) != 0)) {
164+ !secure_permissions(&st, pw->pw_uid)) {
165 logit("Rhosts authentication refused for %.100s: "
166 "bad ownership or modes for home directory.", pw->pw_name);
167 auth_debug_add("Rhosts authentication refused for %.100s: "
168@@ -283,8 +282,7 @@
169 * allowing access to their account by anyone.
170 */
171 if (options.strict_modes &&
172- ((st.st_uid != 0 && st.st_uid != pw->pw_uid) ||
173- (st.st_mode & 022) != 0)) {
174+ !secure_permissions(&st, pw->pw_uid)) {
175 logit("Rhosts authentication refused for %.100s: bad modes for %.200s",
176 pw->pw_name, buf);
177 auth_debug_add("Bad file modes for %.200s", buf);