Gentoo Archives: gentoo-commits

From: Andreas Sturmlechner <asturm@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: kde-plasma/kwallet-pam/, kde-plasma/kwallet-pam/files/
Date: Thu, 31 Aug 2017 20:55:04
Message-Id: 1504212831.de57d49c49b3497e738dd0b32c4c0a00fb3e3f41.asturm@gentoo
1 commit: de57d49c49b3497e738dd0b32c4c0a00fb3e3f41
2 Author: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
3 AuthorDate: Thu Aug 31 19:50:00 2017 +0000
4 Commit: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
5 CommitDate: Thu Aug 31 20:53:51 2017 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=de57d49c
7
8 kde-plasma/kwallet-pam: Fix memleaks and dropping privileges
9
10 Package-Manager: Portage-2.3.8, Repoman-2.3.3
11
12 .../files/kwallet-pam-5.10.5-check-graphical.patch | 87 +++++++++++
13 .../files/kwallet-pam-5.10.5-cleanups.patch | 173 +++++++++++++++++++++
14 .../files/kwallet-pam-5.10.5-privileges.patch | 49 ++++++
15 .../kwallet-pam/kwallet-pam-5.10.5-r1.ebuild | 59 +++++++
16 4 files changed, 368 insertions(+)
17
18 diff --git a/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-check-graphical.patch b/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-check-graphical.patch
19 new file mode 100644
20 index 00000000000..61ea4604586
21 --- /dev/null
22 +++ b/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-check-graphical.patch
23 @@ -0,0 +1,87 @@
24 +From f3b230f7f3bf39dc46b97a216aa7c28595d20a7a Mon Sep 17 00:00:00 2001
25 +From: Fabian Vogt <fabian@×××××××××××.de>
26 +Date: Thu, 3 Aug 2017 09:50:30 +0200
27 +Subject: Check for a graphical session
28 +
29 +Summary:
30 +Avoid running if it detects a text session. This can be overridden by adding
31 +"force_run" as argument.
32 +
33 +Test Plan:
34 +Put pam_kwallet5.so as optional in a global common-session pam file
35 +that is included by all other services. It is not invoked when logging in from
36 +a tty with getty, sudo or su and still works when using SDDM. When adding
37 +force_run it runs in all cases.
38 +
39 +Reviewers: #plasma
40 +
41 +Subscribers: plasma-devel
42 +
43 +Tags: #plasma
44 +
45 +Differential Revision: https://phabricator.kde.org/D7125
46 +---
47 + pam_kwallet.c | 26 ++++++++++++++++++++++++++
48 + 1 file changed, 26 insertions(+)
49 +
50 +diff --git a/pam_kwallet.c b/pam_kwallet.c
51 +index cba57e7..46720a5 100644
52 +--- a/pam_kwallet.c
53 ++++ b/pam_kwallet.c
54 +@@ -72,6 +72,7 @@ const static char *kwalletd = NULL;
55 + const static char *socketPath = NULL;
56 + const static char *kwalletPamDataKey = NULL;
57 + const static char *logPrefix = NULL;
58 ++static int force_run = 0;
59 +
60 + #ifdef KWALLET5
61 + const static char *envVar = "PAM_KWALLET5_LOGIN";
62 +@@ -98,6 +99,8 @@ static void parseArguments(int argc, const char **argv)
63 + kwalletd = argv[x] + 9;
64 + } else if (strstr(argv[x], "socketPath=") != NULL) {
65 + socketPath= argv[x] + 11;
66 ++ } else if (strcmp(argv[x], "force_run") == 0) {
67 ++ force_run = 1;
68 + }
69 + }
70 + #ifdef KWALLET5
71 +@@ -246,6 +249,24 @@ static void cleanup_free(pam_handle_t *pamh, void *ptr, int error_status)
72 + free(ptr);
73 + }
74 +
75 ++static int is_graphical_session(pam_handle_t *pamh)
76 ++{
77 ++ //Detect a graphical session
78 ++ const char *pam_tty = NULL, *pam_xdisplay = NULL,
79 ++ *xdg_session_type = NULL, *display = NULL;
80 ++
81 ++ pam_get_item(pamh, PAM_TTY, (const void**) &pam_tty);
82 ++#ifdef PAM_XDISPLAY
83 ++ pam_get_item(pamh, PAM_XDISPLAY, (const void**) &pam_xdisplay);
84 ++#endif
85 ++ xdg_session_type = get_env(pamh, "XDG_SESSION_TYPE");
86 ++
87 ++ return (pam_xdisplay && strlen(pam_xdisplay) != 0)
88 ++ || (pam_tty && pam_tty[0] == ':')
89 ++ || (xdg_session_type && strcmp(xdg_session_type, "x11") == 0)
90 ++ || (xdg_session_type && strcmp(xdg_session_type, "wayland") == 0);
91 ++}
92 ++
93 + PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
94 + {
95 + pam_syslog(pamh, LOG_INFO, "%s: pam_sm_authenticate\n", logPrefix);
96 +@@ -537,6 +558,11 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, cons
97 +
98 + parseArguments(argc, argv);
99 +
100 ++ if (!force_run && !is_graphical_session(pamh)) {
101 ++ pam_syslog(pamh, LOG_INFO, "%s: not a graphical session, skipping. Use force_run parameter to ignore this.", logPrefix);
102 ++ return PAM_IGNORE;
103 ++ }
104 ++
105 + int result;
106 + result = pam_set_data(pamh, "sm_open_session", "1", NULL);
107 + if (result != PAM_SUCCESS) {
108 +--
109 +cgit v0.11.2
110 +
111
112 diff --git a/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-cleanups.patch b/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-cleanups.patch
113 new file mode 100644
114 index 00000000000..38a333131e9
115 --- /dev/null
116 +++ b/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-cleanups.patch
117 @@ -0,0 +1,173 @@
118 +From a33ec22b96e837899528b05963eae8ea6b01171a Mon Sep 17 00:00:00 2001
119 +From: Fabian Vogt <fabian@×××××××××××.de>
120 +Date: Thu, 3 Aug 2017 09:02:14 +0200
121 +Subject: Several cleanups
122 +
123 +Summary:
124 +- No cppcheck warnings anymore
125 +- Use snprintf everywhere
126 +- Avoid pointless multiplication with sizeof(char)
127 +- Avoid memory leaks
128 +
129 +Test Plan: Still builds, works the same as before.
130 +
131 +Reviewers: #plasma
132 +
133 +Subscribers: plasma-devel
134 +
135 +Tags: #plasma
136 +
137 +Differential Revision: https://phabricator.kde.org/D7123
138 +---
139 + pam_kwallet.c | 44 ++++++++++++++++++++++++++++++++------------
140 + 1 file changed, 32 insertions(+), 12 deletions(-)
141 +
142 +diff --git a/pam_kwallet.c b/pam_kwallet.c
143 +index d88c5e0..cba57e7 100644
144 +--- a/pam_kwallet.c
145 ++++ b/pam_kwallet.c
146 +@@ -151,13 +151,14 @@ static int set_env(pam_handle_t *pamh, const char *name, const char *value)
147 + //We do not return because pam_putenv might work
148 + }
149 +
150 +- char *pamEnv = malloc(strlen(name) + strlen(value) + 2); //2 is for = and \0
151 ++ size_t pamEnvSize = strlen(name) + strlen(value) + 2; //2 is for = and \0
152 ++ char *pamEnv = malloc(pamEnvSize);
153 + if (!pamEnv) {
154 + pam_syslog(pamh, LOG_WARNING, "%s: Impossible to allocate memory for pamEnv", logPrefix);
155 + return -1;
156 + }
157 +
158 +- sprintf (pamEnv, "%s=%s", name, value);
159 ++ snprintf (pamEnv, pamEnvSize, "%s=%s", name, value);
160 + int ret = pam_putenv(pamh, pamEnv);
161 + free(pamEnv);
162 +
163 +@@ -240,6 +241,11 @@ cleanup:
164 + return result;
165 + }
166 +
167 ++static void cleanup_free(pam_handle_t *pamh, void *ptr, int error_status)
168 ++{
169 ++ free(ptr);
170 ++}
171 ++
172 + PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
173 + {
174 + pam_syslog(pamh, LOG_INFO, "%s: pam_sm_authenticate\n", logPrefix);
175 +@@ -297,14 +303,17 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
176 + return PAM_IGNORE;
177 + }
178 +
179 +- char *key = malloc(sizeof(char) * KWALLET_PAM_KEYSIZE);
180 +- if (kwallet_hash(password, userInfo, key) != 0) {
181 ++ char *key = malloc(KWALLET_PAM_KEYSIZE);
182 ++ if (!key || kwallet_hash(password, userInfo, key) != 0) {
183 ++ free(key);
184 + pam_syslog(pamh, LOG_ERR, "%s: Fail into creating the hash", logPrefix);
185 + return PAM_IGNORE;
186 + }
187 +
188 +- result = pam_set_data(pamh, kwalletPamDataKey, key, NULL);
189 ++ result = pam_set_data(pamh, kwalletPamDataKey, key, cleanup_free);
190 ++
191 + if (result != PAM_SUCCESS) {
192 ++ free(key);
193 + pam_syslog(pamh, LOG_ERR, "%s: Impossible to store the hashed password: %s", logPrefix
194 + , pam_strerror(pamh, result));
195 + return PAM_IGNORE;
196 +@@ -385,9 +394,8 @@ cleanup:
197 + static int better_write(int fd, const char *buffer, int len)
198 + {
199 + size_t writtenBytes = 0;
200 +- int result;
201 + while(writtenBytes < len) {
202 +- result = write(fd, buffer + writtenBytes, len - writtenBytes);
203 ++ int result = write(fd, buffer + writtenBytes, len - writtenBytes);
204 + if (result < 0) {
205 + if (errno != EAGAIN && errno != EINTR) {
206 + return -1;
207 +@@ -450,6 +458,7 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
208 + if (result != PAM_SUCCESS) {
209 + pam_syslog(pamh, LOG_ERR, "%s: Impossible to set %s env, %s",
210 + logPrefix, envVar, pam_strerror(pamh, result));
211 ++ free(fullSocket);
212 + return;
213 + }
214 +
215 +@@ -459,12 +468,15 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
216 + if (strlen(fullSocket) > sizeof(local.sun_path)) {
217 + pam_syslog(pamh, LOG_ERR, "%s: socket path %s too long to open",
218 + logPrefix, fullSocket);
219 ++ free(fullSocket);
220 + return;
221 + }
222 + strcpy(local.sun_path, fullSocket);
223 ++ free(fullSocket);
224 ++ fullSocket = NULL;
225 + unlink(local.sun_path);//Just in case it exists from a previous login
226 +
227 +- pam_syslog(pamh, LOG_INFO, "%s: final socket path: %s", logPrefix, fullSocket);
228 ++ pam_syslog(pamh, LOG_INFO, "%s: final socket path: %s", logPrefix, local.sun_path);
229 +
230 + size_t len = strlen(local.sun_path) + sizeof(local.sun_family);
231 + if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
232 +@@ -477,7 +489,7 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
233 + return;
234 + }
235 +
236 +- if (chown(fullSocket, userInfo->pw_uid, userInfo->pw_gid) == -1) {
237 ++ if (chown(local.sun_path, userInfo->pw_uid, userInfo->pw_gid) == -1) {
238 + pam_syslog(pamh, LOG_INFO, "%s: Couldn't change ownership of the socket", logPrefix);
239 + return;
240 + }
241 +@@ -655,7 +667,8 @@ int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key)
242 + #else
243 + char *fixpath = "share/apps/kwallet/kdewallet.salt";
244 + #endif
245 +- char *path = (char*) malloc(strlen(userInfo->pw_dir) + strlen(kdehome) + strlen(fixpath) + 3);//3 == / and \0
246 ++ size_t pathSize = strlen(userInfo->pw_dir) + strlen(kdehome) + strlen(fixpath) + 3;//3 == /, / and \0
247 ++ char *path = (char*) malloc(pathSize);
248 + sprintf(path, "%s/%s/%s", userInfo->pw_dir, kdehome, fixpath);
249 +
250 + struct stat info;
251 +@@ -666,21 +679,26 @@ int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key)
252 + FILE *fd = fopen(path, "r");
253 + if (fd == NULL) {
254 + syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
255 ++ free(path);
256 + return 1;
257 + }
258 +- salt = (char*) malloc(sizeof(char) * KWALLET_PAM_SALTSIZE);
259 ++ salt = (char*) malloc(KWALLET_PAM_SALTSIZE);
260 + memset(salt, '\0', KWALLET_PAM_SALTSIZE);
261 + fread(salt, KWALLET_PAM_SALTSIZE, 1, fd);
262 + fclose(fd);
263 + }
264 ++ free(path);
265 ++
266 + if (salt == NULL) {
267 + syslog(LOG_ERR, "%s-kwalletd: Couldn't create or read the salt file", logPrefix);
268 + return 1;
269 + }
270 +
271 + gcry_error_t error;
272 ++
273 + error = gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0);
274 + if (error != 0) {
275 ++ free(salt);
276 + syslog(LOG_ERR, "%s-kwalletd: Can't get secure memory: %d", logPrefix, error);
277 + return 1;
278 + }
279 +@@ -691,5 +709,7 @@ int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key)
280 + GCRY_KDF_PBKDF2, GCRY_MD_SHA512,
281 + salt, KWALLET_PAM_SALTSIZE,
282 + KWALLET_PAM_ITERATIONS,KWALLET_PAM_KEYSIZE, key);
283 +- return 0;
284 ++
285 ++ free(salt);
286 ++ return (int) error; // gcry_kdf_derive returns 0 on success
287 + }
288 +--
289 +cgit v0.11.2
290 +
291
292 diff --git a/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-privileges.patch b/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-privileges.patch
293 new file mode 100644
294 index 00000000000..8b45b293bbf
295 --- /dev/null
296 +++ b/kde-plasma/kwallet-pam/files/kwallet-pam-5.10.5-privileges.patch
297 @@ -0,0 +1,49 @@
298 +From 1a01e1eb870e1ab1d96a8641f1f3500af646c974 Mon Sep 17 00:00:00 2001
299 +From: Fabian Vogt <fabian@×××××××××××.de>
300 +Date: Thu, 3 Aug 2017 09:27:10 +0200
301 +Subject: Avoid dropping privileges by initializing gcrypt secmem
302 +
303 +Summary:
304 +It's a documented side effect that initialization of secure memory in gcrypt
305 +drops privileges if getuid() != geteuid(). This results in breaking setuid
306 +callers, like sudo or su.
307 +
308 +Test Plan: Can use sudo again when pam_kwallet is involved.
309 +
310 +Reviewers: #plasma
311 +
312 +Subscribers: plasma-devel
313 +
314 +Tags: #plasma
315 +
316 +Differential Revision: https://phabricator.kde.org/D7124
317 +---
318 + pam_kwallet.c | 6 ++++++
319 + 1 file changed, 6 insertions(+)
320 +
321 +diff --git a/pam_kwallet.c b/pam_kwallet.c
322 +index 46720a5..20d9603 100644
323 +--- a/pam_kwallet.c
324 ++++ b/pam_kwallet.c
325 +@@ -722,12 +722,18 @@ int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key)
326 +
327 + gcry_error_t error;
328 +
329 ++ /* We cannot call GCRYCTL_INIT_SECMEM as it drops privileges if getuid() != geteuid().
330 ++ * PAM modules are in many cases executed through setuid binaries, which this call
331 ++ * would break.
332 ++ * It was never effective anyway as neither key nor passphrase are in secure memory,
333 ++ * which is a prerequisite for secure operation...
334 + error = gcry_control(GCRYCTL_INIT_SECMEM, 32768, 0);
335 + if (error != 0) {
336 + free(salt);
337 + syslog(LOG_ERR, "%s-kwalletd: Can't get secure memory: %d", logPrefix, error);
338 + return 1;
339 + }
340 ++ */
341 +
342 + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
343 +
344 +--
345 +cgit v0.11.2
346 +
347
348 diff --git a/kde-plasma/kwallet-pam/kwallet-pam-5.10.5-r1.ebuild b/kde-plasma/kwallet-pam/kwallet-pam-5.10.5-r1.ebuild
349 new file mode 100644
350 index 00000000000..5798e8eaed5
351 --- /dev/null
352 +++ b/kde-plasma/kwallet-pam/kwallet-pam-5.10.5-r1.ebuild
353 @@ -0,0 +1,59 @@
354 +# Copyright 1999-2017 Gentoo Foundation
355 +# Distributed under the terms of the GNU General Public License v2
356 +
357 +EAPI=6
358 +
359 +inherit kde5
360 +
361 +DESCRIPTION="KWallet PAM module to not enter password again"
362 +LICENSE="LGPL-2.1"
363 +KEYWORDS="~amd64 ~arm ~x86"
364 +IUSE=""
365 +
366 +DEPEND="
367 + dev-libs/libgcrypt:0=
368 + virtual/pam
369 +"
370 +RDEPEND="${DEPEND}
371 + net-misc/socat
372 +"
373 +
374 +PATCHES=(
375 + "${FILESDIR}/${P}-cleanups.patch"
376 + "${FILESDIR}/${P}-check-graphical.patch"
377 + "${FILESDIR}/${P}-privileges.patch"
378 +)
379 +
380 +src_configure() {
381 + local mycmakeargs=(
382 + -DCMAKE_INSTALL_LIBDIR="/$(get_libdir)"
383 + -DKWALLET4=0
384 + )
385 + kde5_src_configure
386 +}
387 +
388 +pkg_postinst() {
389 + check_dm() {
390 + if [[ -e "${ROOT}${2}" ]] ; then
391 + if grep -Eq "auth\s+optional\s+pam_kwallet5.so" "${ROOT}${2}" && \
392 + grep -Eq "session\s+optional\s+pam_kwallet5.so" "${ROOT}${2}" ; then
393 + elog " ${1} - ${2} ...GOOD"
394 + else
395 + ewarn " ${1} - ${2} ...BAD"
396 + fi
397 + fi
398 + }
399 + elog "This package enables auto-unlocking of kde-frameworks/kwallet:5."
400 + elog "List of things to make it work:"
401 + elog "1. Use standard blowfish encryption instead of GPG"
402 + elog "2. Use same password for login and kwallet"
403 + elog "3. A display manager with support for PAM"
404 + elog "4.a Have the following lines in the display manager's pam.d file:"
405 + elog " -auth optional pam_kwallet5.so"
406 + elog " -session optional pam_kwallet5.so auto_start"
407 + elog "4.b Checking installed DMs..."
408 + has_version "x11-misc/sddm" && check_dm "SDDM" "/etc/pam.d/sddm"
409 + has_version "x11-misc/lightdm" && check_dm "LightDM" "/etc/pam.d/lightdm"
410 + elog
411 + elog "See also: https://wiki.gentoo.org/wiki/KDE#KWallet_auto-unlocking"
412 +}