1 | /** |
2 | * This file is part of the KDE project |
3 | * Copyright (C) 2008 Michael Leupold <lemma@confuego.org> |
4 | * Copyright (C) 2014 Alejandro Fiestas Olivares <afiestas@kde.org> |
5 | * |
6 | * This library is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Library General Public |
8 | * License version 2 as published by the Free Software Foundation. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Library General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Library General Public License |
16 | * along with this library; see the file COPYING.LIB. If not, write to |
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | * Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | #include <kuniqueapplication.h> |
22 | #include <kaboutdata.h> |
23 | #include <kcmdlineargs.h> |
24 | #include <kdebug.h> |
25 | #include <kconfig.h> |
26 | #include <kconfiggroup.h> |
27 | #include <klocale.h> |
28 | #include <stdio.h> |
29 | #include <sys/types.h> |
30 | #include <sys/socket.h> |
31 | #include <sys/un.h> |
32 | #include <unistd.h> |
33 | #include "kwalletd.h" |
34 | #include "backend/kwalletbackend.h" //For the hash size |
35 | |
36 | #define BSIZE 1000 |
37 | static int pipefd = 0; |
38 | static int socketfd = 0; |
39 | static bool isWalletEnabled() |
40 | { |
41 | KConfig cfg("kwalletrc" ); |
42 | KConfigGroup walletGroup(&cfg, "Wallet" ); |
43 | return walletGroup.readEntry("Enabled" , true); |
44 | } |
45 | |
46 | //Waits until the PAM_MODULE sends the hash |
47 | static char *waitForHash() |
48 | { |
49 | printf("kwalletd: Waiting for hash on %d-\n" , pipefd); |
50 | int totalRead = 0; |
51 | int readBytes = 0; |
52 | int attemps = 0; |
53 | char *buf = (char*)malloc(sizeof(char) * PBKDF2_SHA512_KEYSIZE); |
54 | memset(buf, '\0', PBKDF2_SHA512_KEYSIZE); |
55 | while(totalRead != PBKDF2_SHA512_KEYSIZE) { |
56 | readBytes = read(pipefd, buf + totalRead, PBKDF2_SHA512_KEYSIZE - totalRead); |
57 | if (readBytes == -1 || attemps > 5) { |
58 | free(buf); |
59 | return NULL; |
60 | } |
61 | totalRead += readBytes; |
62 | ++attemps; |
63 | } |
64 | |
65 | close(pipefd); |
66 | return buf; |
67 | } |
68 | |
69 | //Waits until startkde sends the environment variables |
70 | static int waitForEnvironment() |
71 | { |
72 | printf("kwalletd: waitingForEnvironment on: %d\n" , socketfd); |
73 | |
74 | int s2; |
75 | socklen_t t; |
76 | struct sockaddr_un remote; |
77 | if ((s2 = accept(socketfd, (struct sockaddr *)&remote, &t)) == -1) { |
78 | fprintf(stdout, "kwalletd: Couldn't accept incoming connection\n" ); |
79 | return -1; |
80 | } |
81 | printf("kwalletd: client connected\n" ); |
82 | |
83 | char str[BSIZE]; |
84 | memset(str, '\0', sizeof(char) * BSIZE); |
85 | |
86 | int chop = 0; |
87 | FILE *s3 = fdopen(s2, "r" ); |
88 | while(!feof(s3)) { |
89 | if (fgets(str, BSIZE, s3)) { |
90 | chop = strlen(str) - 1; |
91 | str[chop] = '\0'; |
92 | putenv(strdup(str)); |
93 | } |
94 | } |
95 | printf("kwalletd: client disconnected\n" ); |
96 | close(socketfd); |
97 | return 1; |
98 | } |
99 | |
100 | char* checkPamModule(int argc, char **argv) |
101 | { |
102 | printf("Checking for pam module\n" ); |
103 | char *hash = NULL; |
104 | int x = 1; |
105 | for (; x < argc; ++x) { |
106 | if (strcmp(argv[x], "--pam-login" ) != 0) { |
107 | continue; |
108 | } |
109 | printf("Got pam-login\n" ); |
110 | argv[x] = NULL; |
111 | x++; |
112 | //We need at least 2 extra arguments after --pam-login |
113 | if (x + 1 > argc) { |
114 | printf("Invalid arguments (less than needed)\n" ); |
115 | return NULL; |
116 | } |
117 | |
118 | //first socket for the hash, comes from a pipe |
119 | pipefd = atoi(argv[x]); |
120 | argv[x] = NULL; |
121 | x++; |
122 | //second socket for environemtn, comes from a localsock |
123 | socketfd = atoi(argv[x]); |
124 | argv[x] = NULL; |
125 | break; |
126 | } |
127 | |
128 | if (!pipefd || !socketfd) { |
129 | printf("Lacking a socket, pipe: %d, env:%d\n" , pipefd, socketfd); |
130 | return NULL; |
131 | } |
132 | |
133 | hash = waitForHash(); |
134 | |
135 | if (hash == NULL || waitForEnvironment() == -1) { |
136 | printf("Hash or environment not received\n" ); |
137 | return NULL; |
138 | } |
139 | |
140 | return hash; |
141 | } |
142 | |
143 | extern "C" KDE_EXPORT int kdemain(int argc, char **argv) |
144 | { |
145 | char *hash = NULL; |
146 | if (getenv("PAM_KWALLET_LOGIN" )) { |
147 | hash = checkPamModule(argc, argv); |
148 | } |
149 | |
150 | KAboutData aboutdata("kwalletd" , 0, ki18n("KDE Wallet Service" ), |
151 | "0.2" , ki18n("KDE Wallet Service" ), |
152 | KAboutData::License_LGPL, ki18n("(C) 2002-2008 George Staikos, Michael Leupold, Thiago Maceira, Valentin Rusu" )); |
153 | aboutdata.addAuthor(ki18n("Michael Leupold" ),ki18n("Maintainer" ),"lemma@confuego.org" ); |
154 | aboutdata.addAuthor(ki18n("George Staikos" ),ki18n("Former maintainer" ),"staikos@kde.org" ); |
155 | aboutdata.addAuthor(ki18n("Thiago Maceira" ),ki18n("D-Bus Interface" ),"thiago@kde.org" ); |
156 | aboutdata.addAuthor(ki18n("Valentin Rusu" ),ki18n("GPG backend support" ),"kde@rusu.info" ); |
157 | |
158 | aboutdata.setProgramIconName("kwalletmanager" ); |
159 | |
160 | KCmdLineArgs::init( argc, argv, &aboutdata ); |
161 | KUniqueApplication::addCmdLineOptions(); |
162 | KUniqueApplication app; |
163 | |
164 | // This app is started automatically, no need for session management |
165 | app.disableSessionManagement(); |
166 | app.setQuitOnLastWindowClosed( false ); |
167 | |
168 | // check if kwallet is disabled |
169 | if (!isWalletEnabled()) { |
170 | kDebug() << "kwalletd is disabled!" ; |
171 | return (0); |
172 | } |
173 | |
174 | if (!KUniqueApplication::start()) |
175 | { |
176 | kDebug() << "kwalletd is already running!" ; |
177 | return (0); |
178 | } |
179 | |
180 | kDebug() << "kwalletd started" ; |
181 | KWalletD walletd; |
182 | if (hash) { |
183 | kDebug() << "LOGIN INSIDE!" ; |
184 | QByteArray passHash(hash, PBKDF2_SHA512_KEYSIZE); |
185 | int wallet = walletd.pamOpen(KWallet::Wallet::LocalWallet(), passHash, 0); |
186 | kDebug() << "Wallet handler: " << wallet; |
187 | free(hash); |
188 | } else { |
189 | kDebug() << "Not pam login" ; |
190 | } |
191 | return app.exec(); |
192 | } |
193 | |