ipc/keystore/KeyStore.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:8a648b13ecc1
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim: set sw=4 ts=8 et ft=cpp: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include <fcntl.h>
8 #include <sys/stat.h>
9
10 #undef CHROMIUM_LOG
11 #if defined(MOZ_WIDGET_GONK)
12 #include <android/log.h>
13 #define CHROMIUM_LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk", args)
14 #else
15 #define CHROMIUM_LOG(args...) printf(args);
16 #endif
17
18 #include "KeyStore.h"
19 #include "jsfriendapi.h"
20 #include "MainThreadUtils.h" // For NS_IsMainThread.
21
22 #include "plbase64.h"
23 #include "certdb.h"
24 #include "ScopedNSSTypes.h"
25
26 using namespace mozilla::ipc;
27
28 namespace mozilla {
29 namespace ipc {
30
31 static const char* KEYSTORE_SOCKET_NAME = "keystore";
32 static const char* KEYSTORE_SOCKET_PATH = "/dev/socket/keystore";
33
34 int
35 KeyStoreConnector::Create()
36 {
37 MOZ_ASSERT(!NS_IsMainThread());
38
39 int fd;
40
41 unlink(KEYSTORE_SOCKET_PATH);
42
43 fd = socket(AF_LOCAL, SOCK_STREAM, 0);
44
45 if (fd < 0) {
46 NS_WARNING("Could not open keystore socket!");
47 return -1;
48 }
49
50 return fd;
51 }
52
53 bool
54 KeyStoreConnector::CreateAddr(bool aIsServer,
55 socklen_t& aAddrSize,
56 sockaddr_any& aAddr,
57 const char* aAddress)
58 {
59 // Keystore socket must be server
60 MOZ_ASSERT(aIsServer);
61
62 aAddr.un.sun_family = AF_LOCAL;
63 if(strlen(KEYSTORE_SOCKET_PATH) > sizeof(aAddr.un.sun_path)) {
64 NS_WARNING("Address too long for socket struct!");
65 return false;
66 }
67 strcpy((char*)&aAddr.un.sun_path, KEYSTORE_SOCKET_PATH);
68 aAddrSize = strlen(KEYSTORE_SOCKET_PATH) + offsetof(struct sockaddr_un, sun_path) + 1;
69
70 return true;
71 }
72
73 bool
74 KeyStoreConnector::SetUp(int aFd)
75 {
76 return true;
77 }
78
79 bool
80 KeyStoreConnector::SetUpListenSocket(int aFd)
81 {
82 // Allow access of wpa_supplicant(different user, differnt group)
83 chmod(KEYSTORE_SOCKET_PATH, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
84
85 return true;
86 }
87
88 void
89 KeyStoreConnector::GetSocketAddr(const sockaddr_any& aAddr,
90 nsAString& aAddrStr)
91 {
92 // Unused.
93 MOZ_CRASH("This should never be called!");
94 }
95
96 static char *
97 get_cert_db_filename(void *arg, int vers)
98 {
99 static char keystoreDbPath[] = "/data/misc/wifi/keystore";
100 return keystoreDbPath;
101 }
102
103 KeyStore::KeyStore()
104 {
105 // Initial NSS
106 certdb = CERT_GetDefaultCertDB();
107
108 Listen();
109 }
110
111 void
112 KeyStore::Shutdown()
113 {
114 mShutdown = true;
115 CloseSocket();
116 }
117
118 void
119 KeyStore::Listen()
120 {
121 ListenSocket(new KeyStoreConnector());
122
123 ResetHandlerInfo();
124 }
125
126 void
127 KeyStore::ResetHandlerInfo()
128 {
129 mHandlerInfo.state = STATE_IDLE;
130 mHandlerInfo.command = 0;
131 mHandlerInfo.paramCount = 0;
132 mHandlerInfo.commandPattern = nullptr;
133 for (int i = 0; i < MAX_PARAM; i++) {
134 mHandlerInfo.param[i].length = 0;
135 memset(mHandlerInfo.param[i].data, 0, VALUE_SIZE);
136 }
137 }
138
139 bool
140 KeyStore::CheckSize(UnixSocketRawData *aMessage, size_t aExpectSize)
141 {
142 return (aMessage->mSize - aMessage->mCurrentWriteOffset >= aExpectSize) ?
143 true : false;
144 }
145
146 bool
147 KeyStore::ReadCommand(UnixSocketRawData *aMessage)
148 {
149 if (mHandlerInfo.state != STATE_IDLE) {
150 NS_WARNING("Wrong state in ReadCommand()!");
151 return false;
152 }
153
154 if (!CheckSize(aMessage, 1)) {
155 NS_WARNING("Data size error in ReadCommand()!");
156 return false;
157 }
158
159 mHandlerInfo.command = aMessage->mData[aMessage->mCurrentWriteOffset];
160 aMessage->mCurrentWriteOffset++;
161
162 // Find corrsponding command pattern
163 const struct ProtocolCommand *command = commands;
164 while (command->command && command->command != mHandlerInfo.command) {
165 command++;
166 }
167
168 if (!command->command) {
169 NS_WARNING("Unsupported command!");
170 return false;
171 }
172
173 // Get command pattern.
174 mHandlerInfo.commandPattern = command;
175 if (command->paramNum) {
176 // Read command parameter if needed.
177 mHandlerInfo.state = STATE_READ_PARAM_LEN;
178 } else {
179 mHandlerInfo.state = STATE_PROCESSING;
180 }
181
182 return true;
183 }
184
185 bool
186 KeyStore::ReadLength(UnixSocketRawData *aMessage)
187 {
188 if (mHandlerInfo.state != STATE_READ_PARAM_LEN) {
189 NS_WARNING("Wrong state in ReadLength()!");
190 return false;
191 }
192
193 if (!CheckSize(aMessage, 2)) {
194 NS_WARNING("Data size error in ReadLength()!");
195 return false;
196 }
197
198 // Read length of command parameter.
199 unsigned short dataLength;
200 memcpy(&dataLength, &aMessage->mData[aMessage->mCurrentWriteOffset], 2);
201 aMessage->mCurrentWriteOffset += 2;
202 mHandlerInfo.param[mHandlerInfo.paramCount].length = ntohs(dataLength);
203
204 mHandlerInfo.state = STATE_READ_PARAM_DATA;
205
206 return true;
207 }
208
209 bool
210 KeyStore::ReadData(UnixSocketRawData *aMessage)
211 {
212 if (mHandlerInfo.state != STATE_READ_PARAM_DATA) {
213 NS_WARNING("Wrong state in ReadData()!");
214 return false;
215 }
216
217 if (!CheckSize(aMessage, mHandlerInfo.param[mHandlerInfo.paramCount].length)) {
218 NS_WARNING("Data size error in ReadData()!");
219 return false;
220 }
221
222 // Read command parameter.
223 memcpy(mHandlerInfo.param[mHandlerInfo.paramCount].data,
224 &aMessage->mData[aMessage->mCurrentWriteOffset],
225 mHandlerInfo.param[mHandlerInfo.paramCount].length);
226 aMessage->mCurrentWriteOffset += mHandlerInfo.param[mHandlerInfo.paramCount].length;
227 mHandlerInfo.paramCount++;
228
229 if (mHandlerInfo.paramCount == mHandlerInfo.commandPattern->paramNum) {
230 mHandlerInfo.state = STATE_PROCESSING;
231 } else {
232 mHandlerInfo.state = STATE_READ_PARAM_LEN;
233 }
234
235 return true;
236 }
237
238 // Transform base64 certification data into DER format
239 void
240 KeyStore::FormatCaData(const uint8_t *aCaData, int aCaDataLength,
241 const char *aName, const uint8_t **aFormatData,
242 int &aFormatDataLength)
243 {
244 int bufSize = strlen(CA_BEGIN) + strlen(CA_END) + strlen(CA_TAILER) * 2 +
245 strlen(aName) * 2 + aCaDataLength + aCaDataLength/CA_LINE_SIZE + 2;
246 char *buf = (char *)malloc(bufSize);
247
248 aFormatDataLength = bufSize;
249 *aFormatData = (const uint8_t *)buf;
250
251 char *ptr = buf;
252 int len;
253
254 // Create DER header.
255 len = snprintf(ptr, bufSize, "%s%s%s", CA_BEGIN, aName, CA_TAILER);
256 ptr += len;
257 bufSize -= len;
258
259 // Split base64 data in lines.
260 int copySize;
261 while (aCaDataLength > 0) {
262 copySize = (aCaDataLength > CA_LINE_SIZE) ? CA_LINE_SIZE : aCaDataLength;
263
264 memcpy(ptr, aCaData, copySize);
265 ptr += copySize;
266 aCaData += copySize;
267 aCaDataLength -= copySize;
268 bufSize -= copySize;
269
270 *ptr = '\n';
271 ptr++;
272 bufSize--;
273 }
274
275 // Create DEA tailer.
276 snprintf(ptr, bufSize, "%s%s%s", CA_END, aName, CA_TAILER);
277 }
278
279 // Status response
280 void
281 KeyStore::SendResponse(ResponseCode aResponse)
282 {
283 if (aResponse == NO_RESPONSE)
284 return;
285
286 uint8_t response = (uint8_t)aResponse;
287 UnixSocketRawData* data = new UnixSocketRawData((const void *)&response, 1);
288 SendSocketData(data);
289 }
290
291 // Data response
292 void
293 KeyStore::SendData(const uint8_t *aData, int aLength)
294 {
295 unsigned short dataLength = htons(aLength);
296
297 UnixSocketRawData* length = new UnixSocketRawData((const void *)&dataLength, 2);
298 SendSocketData(length);
299
300 UnixSocketRawData* data = new UnixSocketRawData((const void *)aData, aLength);
301 SendSocketData(data);
302 }
303
304 void
305 KeyStore::ReceiveSocketData(nsAutoPtr<UnixSocketRawData>& aMessage)
306 {
307 MOZ_ASSERT(NS_IsMainThread());
308
309 bool success = true;
310 while (aMessage->mCurrentWriteOffset < aMessage->mSize ||
311 mHandlerInfo.state == STATE_PROCESSING) {
312 switch (mHandlerInfo.state) {
313 case STATE_IDLE:
314 success = ReadCommand(aMessage);
315 break;
316 case STATE_READ_PARAM_LEN:
317 success = ReadLength(aMessage);
318 break;
319 case STATE_READ_PARAM_DATA:
320 success = ReadData(aMessage);
321 break;
322 case STATE_PROCESSING:
323 success = false;
324 if (mHandlerInfo.command == 'g') {
325 // Get CA
326 const uint8_t *certData;
327 int certDataLength;
328 const char *certName = (const char *)mHandlerInfo.param[0].data;
329
330 // Get cert from NSS by name
331 ScopedCERTCertificate cert(CERT_FindCertByNickname(certdb, certName));
332 if (!cert) {
333 break;
334 }
335
336 char *certDER = PL_Base64Encode((const char *)cert->derCert.data,
337 cert->derCert.len, nullptr);
338 if (!certDER) {
339 break;
340 }
341
342 FormatCaData((const uint8_t *)certDER, strlen(certDER), "CERTIFICATE",
343 &certData, certDataLength);
344 PL_strfree(certDER);
345
346 SendResponse(SUCCESS);
347 SendData(certData, certDataLength);
348 success = true;
349
350 free((void *)certData);
351 }
352
353 ResetHandlerInfo();
354 break;
355 }
356
357 if (!success) {
358 SendResponse(PROTOCOL_ERROR);
359 ResetHandlerInfo();
360 return;
361 }
362 }
363 }
364
365 void
366 KeyStore::OnConnectSuccess()
367 {
368 mShutdown = false;
369 }
370
371 void
372 KeyStore::OnConnectError()
373 {
374 if (!mShutdown) {
375 Listen();
376 }
377 }
378
379 void
380 KeyStore::OnDisconnect()
381 {
382 if (!mShutdown) {
383 Listen();
384 }
385 }
386
387 } // namespace ipc
388 } // namespace mozilla

mercurial