summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2014-02-09 16:09:58 +0000
committerColin Watson <cjwatson@debian.org>2018-10-20 22:54:09 +0100
commit7b931d36ad36a93d2b1811858ca29408ec44ecae (patch)
tree169969b1dbe936bf31ea64d4335152968d56f8d5 /misc.c
parente755ec70d62bfb9b02159123f4e870b00010be77 (diff)
Allow harmless group-writability
Allow secure files (~/.ssh/config, ~/.ssh/authorized_keys, etc.) to be group-writable, provided that the group in question contains only the file's owner. Rejected upstream for IMO incorrect reasons (e.g. a misunderstanding about the contents of gr->gr_mem). Given that per-user groups and umask 002 are the default setup in Debian (for good reasons - this makes operating in setgid directories with other groups much easier), we need to permit this by default. Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1060 Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=314347 Last-Update: 2017-10-04 Patch-Name: user-group-modes.patch
Diffstat (limited to 'misc.c')
-rw-r--r--misc.c58
1 files changed, 53 insertions, 5 deletions
diff --git a/misc.c b/misc.c
index bdc06fdb3..5159e6692 100644
--- a/misc.c
+++ b/misc.c
@@ -58,8 +58,9 @@
58#include <netdb.h> 58#include <netdb.h>
59#ifdef HAVE_PATHS_H 59#ifdef HAVE_PATHS_H
60# include <paths.h> 60# include <paths.h>
61#include <pwd.h>
62#endif 61#endif
62#include <pwd.h>
63#include <grp.h>
63#ifdef SSH_TUN_OPENBSD 64#ifdef SSH_TUN_OPENBSD
64#include <net/if.h> 65#include <net/if.h>
65#endif 66#endif
@@ -1029,6 +1030,55 @@ percent_expand(const char *string, ...)
1029} 1030}
1030 1031
1031int 1032int
1033secure_permissions(struct stat *st, uid_t uid)
1034{
1035 if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid)
1036 return 0;
1037 if ((st->st_mode & 002) != 0)
1038 return 0;
1039 if ((st->st_mode & 020) != 0) {
1040 /* If the file is group-writable, the group in question must
1041 * have exactly one member, namely the file's owner.
1042 * (Zero-member groups are typically used by setgid
1043 * binaries, and are unlikely to be suitable.)
1044 */
1045 struct passwd *pw;
1046 struct group *gr;
1047 int members = 0;
1048
1049 gr = getgrgid(st->st_gid);
1050 if (!gr)
1051 return 0;
1052
1053 /* Check primary group memberships. */
1054 while ((pw = getpwent()) != NULL) {
1055 if (pw->pw_gid == gr->gr_gid) {
1056 ++members;
1057 if (pw->pw_uid != uid)
1058 return 0;
1059 }
1060 }
1061 endpwent();
1062
1063 pw = getpwuid(st->st_uid);
1064 if (!pw)
1065 return 0;
1066
1067 /* Check supplementary group memberships. */
1068 if (gr->gr_mem[0]) {
1069 ++members;
1070 if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
1071 gr->gr_mem[1])
1072 return 0;
1073 }
1074
1075 if (!members)
1076 return 0;
1077 }
1078 return 1;
1079}
1080
1081int
1032tun_open(int tun, int mode, char **ifname) 1082tun_open(int tun, int mode, char **ifname)
1033{ 1083{
1034#if defined(CUSTOM_SYS_TUN_OPEN) 1084#if defined(CUSTOM_SYS_TUN_OPEN)
@@ -1786,8 +1836,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1786 snprintf(err, errlen, "%s is not a regular file", buf); 1836 snprintf(err, errlen, "%s is not a regular file", buf);
1787 return -1; 1837 return -1;
1788 } 1838 }
1789 if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || 1839 if (!secure_permissions(stp, uid)) {
1790 (stp->st_mode & 022) != 0) {
1791 snprintf(err, errlen, "bad ownership or modes for file %s", 1840 snprintf(err, errlen, "bad ownership or modes for file %s",
1792 buf); 1841 buf);
1793 return -1; 1842 return -1;
@@ -1802,8 +1851,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1802 strlcpy(buf, cp, sizeof(buf)); 1851 strlcpy(buf, cp, sizeof(buf));
1803 1852
1804 if (stat(buf, &st) < 0 || 1853 if (stat(buf, &st) < 0 ||
1805 (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || 1854 !secure_permissions(&st, uid)) {
1806 (st.st_mode & 022) != 0) {
1807 snprintf(err, errlen, 1855 snprintf(err, errlen,
1808 "bad ownership or modes for directory %s", buf); 1856 "bad ownership or modes for directory %s", buf);
1809 return -1; 1857 return -1;