summaryrefslogtreecommitdiff
path: root/misc.c
diff options
context:
space:
mode:
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 009e02bc5..634b5060a 100644
--- a/misc.c
+++ b/misc.c
@@ -59,8 +59,9 @@
59#include <netdb.h> 59#include <netdb.h>
60#ifdef HAVE_PATHS_H 60#ifdef HAVE_PATHS_H
61# include <paths.h> 61# include <paths.h>
62#include <pwd.h>
63#endif 62#endif
63#include <pwd.h>
64#include <grp.h>
64#ifdef SSH_TUN_OPENBSD 65#ifdef SSH_TUN_OPENBSD
65#include <net/if.h> 66#include <net/if.h>
66#endif 67#endif
@@ -1104,6 +1105,55 @@ percent_expand(const char *string, ...)
1104} 1105}
1105 1106
1106int 1107int
1108secure_permissions(struct stat *st, uid_t uid)
1109{
1110 if (!platform_sys_dir_uid(st->st_uid) && st->st_uid != uid)
1111 return 0;
1112 if ((st->st_mode & 002) != 0)
1113 return 0;
1114 if ((st->st_mode & 020) != 0) {
1115 /* If the file is group-writable, the group in question must
1116 * have exactly one member, namely the file's owner.
1117 * (Zero-member groups are typically used by setgid
1118 * binaries, and are unlikely to be suitable.)
1119 */
1120 struct passwd *pw;
1121 struct group *gr;
1122 int members = 0;
1123
1124 gr = getgrgid(st->st_gid);
1125 if (!gr)
1126 return 0;
1127
1128 /* Check primary group memberships. */
1129 while ((pw = getpwent()) != NULL) {
1130 if (pw->pw_gid == gr->gr_gid) {
1131 ++members;
1132 if (pw->pw_uid != uid)
1133 return 0;
1134 }
1135 }
1136 endpwent();
1137
1138 pw = getpwuid(st->st_uid);
1139 if (!pw)
1140 return 0;
1141
1142 /* Check supplementary group memberships. */
1143 if (gr->gr_mem[0]) {
1144 ++members;
1145 if (strcmp(pw->pw_name, gr->gr_mem[0]) ||
1146 gr->gr_mem[1])
1147 return 0;
1148 }
1149
1150 if (!members)
1151 return 0;
1152 }
1153 return 1;
1154}
1155
1156int
1107tun_open(int tun, int mode, char **ifname) 1157tun_open(int tun, int mode, char **ifname)
1108{ 1158{
1109#if defined(CUSTOM_SYS_TUN_OPEN) 1159#if defined(CUSTOM_SYS_TUN_OPEN)
@@ -1860,8 +1910,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1860 snprintf(err, errlen, "%s is not a regular file", buf); 1910 snprintf(err, errlen, "%s is not a regular file", buf);
1861 return -1; 1911 return -1;
1862 } 1912 }
1863 if ((!platform_sys_dir_uid(stp->st_uid) && stp->st_uid != uid) || 1913 if (!secure_permissions(stp, uid)) {
1864 (stp->st_mode & 022) != 0) {
1865 snprintf(err, errlen, "bad ownership or modes for file %s", 1914 snprintf(err, errlen, "bad ownership or modes for file %s",
1866 buf); 1915 buf);
1867 return -1; 1916 return -1;
@@ -1876,8 +1925,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
1876 strlcpy(buf, cp, sizeof(buf)); 1925 strlcpy(buf, cp, sizeof(buf));
1877 1926
1878 if (stat(buf, &st) < 0 || 1927 if (stat(buf, &st) < 0 ||
1879 (!platform_sys_dir_uid(st.st_uid) && st.st_uid != uid) || 1928 !secure_permissions(&st, uid)) {
1880 (st.st_mode & 022) != 0) {
1881 snprintf(err, errlen, 1929 snprintf(err, errlen,
1882 "bad ownership or modes for directory %s", buf); 1930 "bad ownership or modes for directory %s", buf);
1883 return -1; 1931 return -1;