Codebase list kwallet-pam / 8f3716b
Drop upstream patches Maximiliano Curia 5 years ago
4 changed file(s) with 0 addition(s) and 386 deletion(s). Raw diff Collapse all Expand all
+0
-50
debian/patches/Avoid-giving-an-stderr-to-kwallet.patch less more
0 From: Maximiliano Curia <maxy@gnuservers.com.ar>
1 Date: Fri, 4 May 2018 22:06:06 +0200
2 Subject: Avoid giving an stderr to kwallet
3
4 Summary:
5 The fixes for CVE-2018-10380 introduced a regression for most users not
6 using kde, and some for kde sessions. In particular the reorder of the
7 close calls and creating a new socket caused that the socket is always
8 assigned the file descriptor 2, aka stderr.
9
10 BUG: 393856
11
12 Test Plan: It works
13
14 Reviewers: #plasma, aacid
15
16 Reviewed By: aacid
17
18 Subscribers: asturmlechner, rdieter, davidedmundson, plasma-devel
19
20 Tags: #plasma
21
22 Differential Revision: https://phabricator.kde.org/D12702
23 ---
24 pam_kwallet.c | 5 ++++-
25 1 file changed, 4 insertions(+), 1 deletion(-)
26
27 diff --git a/pam_kwallet.c b/pam_kwallet.c
28 index b9c984a..661ed8d 100644
29 --- a/pam_kwallet.c
30 +++ b/pam_kwallet.c
31 @@ -375,7 +375,8 @@ static int drop_privileges(struct passwd *userInfo)
32 static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], char *fullSocket)
33 {
34 //In the child pam_syslog does not work, using syslog directly
35 - int x = 2;
36 + //keep stderr open so socket doesn't returns us that fd
37 + int x = 3;
38 //Close fd that are not of interest of kwallet
39 for (; x < 64; ++x) {
40 if (x != toWalletPipe[0]) {
41 @@ -424,6 +425,8 @@ static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toW
42 pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't listen in socket\n", logPrefix);
43 return;
44 }
45 + //finally close stderr
46 + close(2);
47
48 // Fork twice to daemonize kwallet
49 setsid();
+0
-202
debian/patches/Move-salt-creation-to-an-unprivileged-process.patch less more
0 From: Albert Astals Cid <aacid@kde.org>
1 Date: Tue, 1 May 2018 12:29:02 +0200
2 Subject: Move salt creation to an unprivileged process
3
4 Opening files for writing as root is very tricky since through the power
5 of symlinks we can get tricked to write in places we don't want to and
6 we don't really need to be root to create the salt file
7 ---
8 pam_kwallet.c | 121 ++++++++++++++++++++++++++++++++++------------------------
9 1 file changed, 71 insertions(+), 50 deletions(-)
10
11 diff --git a/pam_kwallet.c b/pam_kwallet.c
12 index 20d9603..083c9aa 100644
13 --- a/pam_kwallet.c
14 +++ b/pam_kwallet.c
15 @@ -82,7 +82,7 @@ const static char *envVar = "PAM_KWALLET_LOGIN";
16
17 static int argumentsParsed = -1;
18
19 -int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key);
20 +int kwallet_hash(pam_handle_t *pamh, const char *passphrase, struct passwd *userInfo, char *key);
21
22 static void parseArguments(int argc, const char **argv)
23 {
24 @@ -325,7 +325,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
25 }
26
27 char *key = malloc(KWALLET_PAM_KEYSIZE);
28 - if (!key || kwallet_hash(password, userInfo, key) != 0) {
29 + if (!key || kwallet_hash(pamh, password, userInfo, key) != 0) {
30 free(key);
31 pam_syslog(pamh, LOG_ERR, "%s: Fail into creating the hash", logPrefix);
32 return PAM_IGNORE;
33 @@ -352,6 +352,26 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
34 return PAM_SUCCESS;
35 }
36
37 +static int drop_privileges(struct passwd *userInfo)
38 +{
39 + /* When dropping privileges from root, the `setgroups` call will
40 + * remove any extraneous groups. If we don't call this, then
41 + * even though our uid has dropped, we may still have groups
42 + * that enable us to do super-user things. This will fail if we
43 + * aren't root, so don't bother checking the return value, this
44 + * is just done as an optimistic privilege dropping function.
45 + */
46 + setgroups(0, NULL);
47 +
48 + //Change to the user in case we are not it yet
49 + if (setgid (userInfo->pw_gid) < 0 || setuid (userInfo->pw_uid) < 0 ||
50 + setegid (userInfo->pw_gid) < 0 || seteuid (userInfo->pw_uid) < 0) {
51 + return -1;
52 + }
53 +
54 + return 0;
55 +}
56 +
57 static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], int envSocket)
58 {
59 //In the child pam_syslog does not work, using syslog directly
60 @@ -366,18 +386,8 @@ static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toW
61 //This is the side of the pipe PAM will send the hash to
62 close (toWalletPipe[1]);
63
64 - /* When dropping privileges from root, the `setgroups` call will
65 - * remove any extraneous groups. If we don't call this, then
66 - * even though our uid has dropped, we may still have groups
67 - * that enable us to do super-user things. This will fail if we
68 - * aren't root, so don't bother checking the return value, this
69 - * is just done as an optimistic privilege dropping function.
70 - */
71 - setgroups(0, NULL);
72 -
73 //Change to the user in case we are not it yet
74 - if (setgid (userInfo->pw_gid) < 0 || setuid (userInfo->pw_uid) < 0 ||
75 - setegid (userInfo->pw_gid) < 0 || seteuid (userInfo->pw_uid) < 0) {
76 + if (drop_privileges(userInfo) < 0) {
77 syslog(LOG_ERR, "%s: could not set gid/uid/euid/egit for kwalletd", logPrefix);
78 goto cleanup;
79 }
80 @@ -619,7 +629,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const c
81 return PAM_SUCCESS;
82 }
83
84 -int mkpath(char *path, struct passwd *userInfo)
85 +static int mkpath(char *path)
86 {
87 struct stat sb;
88 char *slash;
89 @@ -639,10 +649,6 @@ int mkpath(char *path, struct passwd *userInfo)
90 errno != EEXIST)) {
91 syslog(LOG_ERR, "%s: Couldn't create directory: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
92 return (-1);
93 - } else {
94 - if (chown(path, userInfo->pw_uid, userInfo->pw_gid) == -1) {
95 - syslog(LOG_INFO, "%s: Couldn't change ownership of: %s", logPrefix, path);
96 - }
97 }
98 } else if (!S_ISDIR(sb.st_mode)) {
99 return (-1);
100 @@ -654,34 +660,49 @@ int mkpath(char *path, struct passwd *userInfo)
101 return (0);
102 }
103
104 -static char* createNewSalt(const char *path, struct passwd *userInfo)
105 +static void createNewSalt(pam_handle_t *pamh, const char *path, struct passwd *userInfo)
106 {
107 - unlink(path);//in case the file already exists
108 + const int pid = fork();
109 + if (pid == -1) {
110 + pam_syslog(pamh, LOG_ERR, "%s: Couldn't fork to create salt file", logPrefix);
111 + } else if (pid == 0) {
112 + // Child process
113 + if (drop_privileges(userInfo) < 0) {
114 + syslog(LOG_ERR, "%s: could not set gid/uid/euid/egit for salt file creation", logPrefix);
115 + exit(-1);
116 + }
117
118 - char *dir = strdup(path);
119 - dir[strlen(dir) - 14] = '\0';//remove kdewallet.salt
120 - mkpath(dir, userInfo);//create the path in case it does not exists
121 - free(dir);
122 + unlink(path);//in case the file already exists
123
124 - char *salt = gcry_random_bytes(KWALLET_PAM_SALTSIZE, GCRY_STRONG_RANDOM);
125 - FILE *fd = fopen(path, "w");
126 + char *dir = strdup(path);
127 + dir[strlen(dir) - 14] = '\0';//remove kdewallet.salt
128 + mkpath(dir); //create the path in case it does not exists
129 + free(dir);
130
131 - //If the file can't be created
132 - if (fd == NULL) {
133 - syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
134 - return NULL;
135 - }
136 + char *salt = gcry_random_bytes(KWALLET_PAM_SALTSIZE, GCRY_STRONG_RANDOM);
137 + FILE *fd = fopen(path, "w");
138
139 - fwrite(salt, KWALLET_PAM_SALTSIZE, 1, fd);
140 - fclose(fd);
141 + //If the file can't be created
142 + if (fd == NULL) {
143 + syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
144 + exit(-2);
145 + }
146
147 - if (chown(path, userInfo->pw_uid, userInfo->pw_gid) == -1) {
148 - syslog(LOG_ERR, "%s: Couldn't change ownership of the created salt file", logPrefix);
149 - }
150 + fwrite(salt, KWALLET_PAM_SALTSIZE, 1, fd);
151 + fclose(fd);
152
153 - return salt;
154 + exit(0); // success
155 + } else {
156 + // pam process, just wait for child to finish
157 + int status;
158 + waitpid(pid, &status, 0);
159 + if (status != 0) {
160 + pam_syslog(pamh, LOG_ERR, "%s: Couldn't create salt file", logPrefix);
161 + }
162 + }
163 }
164 -int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key)
165 +
166 +int kwallet_hash(pam_handle_t *pamh, const char *passphrase, struct passwd *userInfo, char *key)
167 {
168 if (!gcry_check_version("1.5.0")) {
169 syslog(LOG_ERR, "%s-kwalletd: libcrypt version is too old", logPrefix);
170 @@ -700,19 +721,19 @@ int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key)
171 struct stat info;
172 char *salt = NULL;
173 if (stat(path, &info) != 0 || info.st_size == 0) {
174 - salt = createNewSalt(path, userInfo);
175 - } else {
176 - FILE *fd = fopen(path, "r");
177 - if (fd == NULL) {
178 - syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
179 - free(path);
180 - return 1;
181 - }
182 - salt = (char*) malloc(KWALLET_PAM_SALTSIZE);
183 - memset(salt, '\0', KWALLET_PAM_SALTSIZE);
184 - fread(salt, KWALLET_PAM_SALTSIZE, 1, fd);
185 - fclose(fd);
186 + createNewSalt(pamh, path, userInfo);
187 }
188 +
189 + FILE *fd = fopen(path, "r");
190 + if (fd == NULL) {
191 + syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
192 + free(path);
193 + return 1;
194 + }
195 + salt = (char*) malloc(KWALLET_PAM_SALTSIZE);
196 + memset(salt, '\0', KWALLET_PAM_SALTSIZE);
197 + fread(salt, KWALLET_PAM_SALTSIZE, 1, fd);
198 + fclose(fd);
199 free(path);
200
201 if (salt == NULL) {
+0
-131
debian/patches/Move-socket-creation-to-unprivileged-codepath.patch less more
0 From: Albert Astals Cid <aacid@kde.org>
1 Date: Tue, 1 May 2018 12:32:24 +0200
2 Subject: Move socket creation to unprivileged codepath
3
4 We don't need to be creating the socket as root, and doing so,
5 specially having a chown is problematic security wise.
6 ---
7 pam_kwallet.c | 77 ++++++++++++++++++++++++++++-------------------------------
8 1 file changed, 36 insertions(+), 41 deletions(-)
9
10 diff --git a/pam_kwallet.c b/pam_kwallet.c
11 index 083c9aa..b9c984a 100644
12 --- a/pam_kwallet.c
13 +++ b/pam_kwallet.c
14 @@ -372,13 +372,13 @@ static int drop_privileges(struct passwd *userInfo)
15 return 0;
16 }
17
18 -static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], int envSocket)
19 +static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], char *fullSocket)
20 {
21 //In the child pam_syslog does not work, using syslog directly
22 int x = 2;
23 //Close fd that are not of interest of kwallet
24 for (; x < 64; ++x) {
25 - if (x != toWalletPipe[0] && x != envSocket) {
26 + if (x != toWalletPipe[0]) {
27 close (x);
28 }
29 }
30 @@ -392,6 +392,39 @@ static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toW
31 goto cleanup;
32 }
33
34 + int envSocket;
35 + if ((envSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
36 + pam_syslog(pamh, LOG_ERR, "%s: couldn't create socket", logPrefix);
37 + return;
38 + }
39 +
40 + struct sockaddr_un local;
41 + local.sun_family = AF_UNIX;
42 +
43 + if (strlen(fullSocket) > sizeof(local.sun_path)) {
44 + pam_syslog(pamh, LOG_ERR, "%s: socket path %s too long to open",
45 + logPrefix, fullSocket);
46 + free(fullSocket);
47 + return;
48 + }
49 + strcpy(local.sun_path, fullSocket);
50 + free(fullSocket);
51 + fullSocket = NULL;
52 + unlink(local.sun_path);//Just in case it exists from a previous login
53 +
54 + pam_syslog(pamh, LOG_INFO, "%s: final socket path: %s", logPrefix, local.sun_path);
55 +
56 + size_t len = strlen(local.sun_path) + sizeof(local.sun_family);
57 + if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
58 + pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't bind to local file\n", logPrefix);
59 + return;
60 + }
61 +
62 + if (listen(envSocket, 5) == -1) {
63 + pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't listen in socket\n", logPrefix);
64 + return;
65 + }
66 +
67 // Fork twice to daemonize kwallet
68 setsid();
69 pid_t pid = fork();
70 @@ -452,12 +485,6 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
71 pam_syslog(pamh, LOG_ERR, "%s: Couldn't create pipes", logPrefix);
72 }
73
74 - int envSocket;
75 - if ((envSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
76 - pam_syslog(pamh, LOG_ERR, "%s: couldn't create socket", logPrefix);
77 - return;
78 - }
79 -
80 #ifdef KWALLET5
81 const char *socketPrefix = "kwallet5";
82 #else
83 @@ -493,38 +520,6 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
84 return;
85 }
86
87 - struct sockaddr_un local;
88 - local.sun_family = AF_UNIX;
89 -
90 - if (strlen(fullSocket) > sizeof(local.sun_path)) {
91 - pam_syslog(pamh, LOG_ERR, "%s: socket path %s too long to open",
92 - logPrefix, fullSocket);
93 - free(fullSocket);
94 - return;
95 - }
96 - strcpy(local.sun_path, fullSocket);
97 - free(fullSocket);
98 - fullSocket = NULL;
99 - unlink(local.sun_path);//Just in case it exists from a previous login
100 -
101 - pam_syslog(pamh, LOG_INFO, "%s: final socket path: %s", logPrefix, local.sun_path);
102 -
103 - size_t len = strlen(local.sun_path) + sizeof(local.sun_family);
104 - if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
105 - pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't bind to local file\n", logPrefix);
106 - return;
107 - }
108 -
109 - if (listen(envSocket, 5) == -1) {
110 - pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't listen in socket\n", logPrefix);
111 - return;
112 - }
113 -
114 - if (chown(local.sun_path, userInfo->pw_uid, userInfo->pw_gid) == -1) {
115 - pam_syslog(pamh, LOG_INFO, "%s: Couldn't change ownership of the socket", logPrefix);
116 - return;
117 - }
118 -
119 pid_t pid;
120 int status;
121 switch (pid = fork ()) {
122 @@ -534,7 +529,7 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
123
124 //Child fork, will contain kwalletd
125 case 0:
126 - execute_kwallet(pamh, userInfo, toWalletPipe, envSocket);
127 + execute_kwallet(pamh, userInfo, toWalletPipe, fullSocket);
128 /* Should never be reached */
129 break;
130
0 Move-salt-creation-to-an-unprivileged-process.patch
1 Move-socket-creation-to-unprivileged-codepath.patch
2 Avoid-giving-an-stderr-to-kwallet.patch