summaryrefslogtreecommitdiff
blob: 2f88e0c3ceae6cfdbf9a9b725d6b367b2f201343 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
From 01d4143fda5bddb6dca37b23304dc239a5fb38b5 Mon Sep 17 00:00:00 2001
From: Albert Astals Cid <aacid@kde.org>
Date: Tue, 1 May 2018 12:32:24 +0200
Subject: Move socket creation to unprivileged codepath

We don't need to be creating the socket as root, and doing so,
specially having a chown is problematic security wise.
---
 pam_kwallet.c | 77 ++++++++++++++++++++++++++++-------------------------------
 1 file changed, 36 insertions(+), 41 deletions(-)

diff --git a/pam_kwallet.c b/pam_kwallet.c
index 083c9aa..b9c984a 100644
--- a/pam_kwallet.c
+++ b/pam_kwallet.c
@@ -372,13 +372,13 @@ static int drop_privileges(struct passwd *userInfo)
     return 0;
 }
 
-static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], int envSocket)
+static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], char *fullSocket)
 {
     //In the child pam_syslog does not work, using syslog directly
     int x = 2;
     //Close fd that are not of interest of kwallet
     for (; x < 64; ++x) {
-        if (x != toWalletPipe[0] && x != envSocket) {
+        if (x != toWalletPipe[0]) {
             close (x);
         }
     }
@@ -392,6 +392,39 @@ static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toW
         goto cleanup;
     }
 
+    int envSocket;
+    if ((envSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+        pam_syslog(pamh, LOG_ERR, "%s: couldn't create socket", logPrefix);
+        return;
+    }
+
+    struct sockaddr_un local;
+    local.sun_family = AF_UNIX;
+
+    if (strlen(fullSocket) > sizeof(local.sun_path)) {
+        pam_syslog(pamh, LOG_ERR, "%s: socket path %s too long to open",
+                   logPrefix, fullSocket);
+        free(fullSocket);
+        return;
+    }
+    strcpy(local.sun_path, fullSocket);
+    free(fullSocket);
+    fullSocket = NULL;
+    unlink(local.sun_path);//Just in case it exists from a previous login
+
+    pam_syslog(pamh, LOG_INFO, "%s: final socket path: %s", logPrefix, local.sun_path);
+
+    size_t len = strlen(local.sun_path) + sizeof(local.sun_family);
+    if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
+        pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't bind to local file\n", logPrefix);
+        return;
+    }
+
+    if (listen(envSocket, 5) == -1) {
+        pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't listen in socket\n", logPrefix);
+        return;
+    }
+
     // Fork twice to daemonize kwallet
     setsid();
     pid_t pid = fork();
@@ -452,12 +485,6 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
         pam_syslog(pamh, LOG_ERR, "%s: Couldn't create pipes", logPrefix);
     }
 
-    int envSocket;
-    if ((envSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
-        pam_syslog(pamh, LOG_ERR, "%s: couldn't create socket", logPrefix);
-        return;
-    }
-
 #ifdef KWALLET5
     const char *socketPrefix = "kwallet5";
 #else
@@ -493,38 +520,6 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
         return;
     }
 
-    struct sockaddr_un local;
-    local.sun_family = AF_UNIX;
-
-    if (strlen(fullSocket) > sizeof(local.sun_path)) {
-        pam_syslog(pamh, LOG_ERR, "%s: socket path %s too long to open",
-                   logPrefix, fullSocket);
-        free(fullSocket);
-        return;
-    }
-    strcpy(local.sun_path, fullSocket);
-    free(fullSocket);
-    fullSocket = NULL;
-    unlink(local.sun_path);//Just in case it exists from a previous login
-
-    pam_syslog(pamh, LOG_INFO, "%s: final socket path: %s", logPrefix, local.sun_path);
-
-    size_t len = strlen(local.sun_path) + sizeof(local.sun_family);
-    if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
-        pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't bind to local file\n", logPrefix);
-        return;
-    }
-
-    if (listen(envSocket, 5) == -1) {
-        pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't listen in socket\n", logPrefix);
-        return;
-    }
-
-    if (chown(local.sun_path, userInfo->pw_uid, userInfo->pw_gid) == -1) {
-        pam_syslog(pamh, LOG_INFO, "%s: Couldn't change ownership of the socket", logPrefix);
-        return;
-    }
-
     pid_t pid;
     int status;
     switch (pid = fork ()) {
@@ -534,7 +529,7 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
 
     //Child fork, will contain kwalletd
     case 0:
-        execute_kwallet(pamh, userInfo, toWalletPipe, envSocket);
+        execute_kwallet(pamh, userInfo, toWalletPipe, fullSocket);
         /* Should never be reached */
         break;
 
-- 
cgit v0.11.2