Mercurial > hg
comparison contrib/chg/chg.c @ 30884:a68510b69f41
chg: verify XDG_RUNTIME_DIR
According to the specification [1], $XDG_RUNTIME_DIR should be ignored
unless:
The directory MUST be owned by the user, and he MUST be the only one
having read and write access to it. Its Unix access mode MUST be 0700.
This patch adds a check and ignores it if it does not meet part of the
criteria.
[1]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
author | Jun Wu <quark@fb.com> |
---|---|
date | Mon, 06 Feb 2017 17:01:06 -0800 |
parents | fde9692a02c0 |
children | ca7af5d15b21 |
comparison
equal
deleted
inserted
replaced
30883:fe8ded72e17c | 30884:a68510b69f41 |
---|---|
126 abortmsg("cannot create sockdir %s (file exists)", sockdir); | 126 abortmsg("cannot create sockdir %s (file exists)", sockdir); |
127 if (st.st_uid != geteuid() || st.st_mode & 0077) | 127 if (st.st_uid != geteuid() || st.st_mode & 0077) |
128 abortmsg("insecure sockdir %s", sockdir); | 128 abortmsg("insecure sockdir %s", sockdir); |
129 } | 129 } |
130 | 130 |
131 /* | |
132 * Check if a socket directory exists and is only owned by the current user. | |
133 * Return 1 if so, 0 if not. This is used to check if XDG_RUNTIME_DIR can be | |
134 * used or not. According to the specification [1], XDG_RUNTIME_DIR should be | |
135 * ignored if the directory is not owned by the user with mode 0700. | |
136 * [1]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html | |
137 */ | |
138 static int checkruntimedir(const char *sockdir) | |
139 { | |
140 struct stat st; | |
141 int r = lstat(sockdir, &st); | |
142 if (r < 0) /* ex. does not exist */ | |
143 return 0; | |
144 if (!S_ISDIR(st.st_mode)) /* ex. is a file, not a directory */ | |
145 return 0; | |
146 return st.st_uid == geteuid() && (st.st_mode & 0777) == 0700; | |
147 } | |
148 | |
131 static void getdefaultsockdir(char sockdir[], size_t size) | 149 static void getdefaultsockdir(char sockdir[], size_t size) |
132 { | 150 { |
133 /* by default, put socket file in secure directory | 151 /* by default, put socket file in secure directory |
134 * (${XDG_RUNTIME_DIR}/chg, or /${TMPDIR:-tmp}/chg$UID) | 152 * (${XDG_RUNTIME_DIR}/chg, or /${TMPDIR:-tmp}/chg$UID) |
135 * (permission of socket file may be ignored on some Unices) */ | 153 * (permission of socket file may be ignored on some Unices) */ |
136 const char *runtimedir = getenv("XDG_RUNTIME_DIR"); | 154 const char *runtimedir = getenv("XDG_RUNTIME_DIR"); |
137 int r; | 155 int r; |
138 if (runtimedir) { | 156 if (runtimedir && checkruntimedir(runtimedir)) { |
139 r = snprintf(sockdir, size, "%s/chg", runtimedir); | 157 r = snprintf(sockdir, size, "%s/chg", runtimedir); |
140 } else { | 158 } else { |
141 const char *tmpdir = getenv("TMPDIR"); | 159 const char *tmpdir = getenv("TMPDIR"); |
142 if (!tmpdir) | 160 if (!tmpdir) |
143 tmpdir = "/tmp"; | 161 tmpdir = "/tmp"; |