Old privileges restored
[platform/core/security/key-manager.git] / src / manager / service / ckm-service.cpp
1 /*
2  *  Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  *
16  *
17  * @file        ckm-service.cpp
18  * @author      Bartlomiej Grzelewski (b.grzelewski@samsung.com)
19  * @version     1.0
20  * @brief       CKM service implementation.
21  */
22
23 #include <protocols.h>
24
25 #include <dpl/serialization.h>
26 #include <dpl/log/log.h>
27
28 #include <ckm-service.h>
29 #include <ckm-logic.h>
30
31 namespace {
32 const CKM::InterfaceID SOCKET_ID_CONTROL = 0;
33 const CKM::InterfaceID SOCKET_ID_STORAGE = 1;
34
35 template <typename ...Args>
36 CKM::RawBuffer disallowed(int command, int msgID, Args&&... args) {
37     LogError("Disallowed command: " << command);
38     return CKM::MessageBuffer::Serialize(command,
39                                          msgID,
40                                          CKM_API_ERROR_ACCESS_DENIED,
41                                          std::move(args)...).Pop();
42 }
43 } // namespace anonymous
44
45 namespace CKM {
46
47 CKMService::CKMService()
48   : m_logic(new CKMLogic)
49 {}
50
51 CKMService::~CKMService() {
52     delete m_logic;
53 }
54
55 void CKMService::Start() {
56     Create();
57 }
58
59 void CKMService::Stop() {
60     Join();
61 }
62
63 GenericSocketService::ServiceDescriptionVector CKMService::GetServiceDescription()
64 {
65     return ServiceDescriptionVector {
66         {SERVICE_SOCKET_CKM_CONTROL, "http://tizen.org/privilege/keymanager.admin", SOCKET_ID_CONTROL},
67         {SERVICE_SOCKET_CKM_STORAGE, "http://tizen.org/privilege/keymanager", SOCKET_ID_STORAGE}
68     };
69 }
70
71 void CKMService::SetCommManager(CommMgr *manager)
72 {
73     ThreadService::SetCommManager(manager);
74     Register(*manager);
75 }
76
77 bool CKMService::ProcessOne(
78     const ConnectionID &conn,
79     ConnectionInfo &info,
80     bool allowed)
81 {
82     LogDebug ("process One");
83     RawBuffer response;
84
85     Try {
86         if (!info.buffer.Ready())
87             return false;
88
89         if (info.interfaceID == SOCKET_ID_CONTROL)
90             response = ProcessControl(info.buffer);
91         else
92             response = ProcessStorage(info.credentials, info.buffer, allowed);
93
94         m_serviceManager->Write(conn, response);
95
96         return true;
97     } Catch (MessageBuffer::Exception::Base) {
98         LogError("Broken protocol. Closing socket.");
99     } Catch (Exception::BrokenProtocol) {
100         LogError("Broken protocol. Closing socket.");
101     } catch (const DataType::Exception::Base &e) {
102         LogError("Closing socket. DBDataType::Exception: " << e.DumpToString());
103     } catch (const std::string &e) {
104         LogError("String exception(" << e << "). Closing socket");
105     } catch (const std::exception &e) {
106         LogError("Std exception:: " << e.what());
107     } catch (...) {
108         LogError("Unknown exception. Closing socket.");
109     }
110
111     m_serviceManager->Close(conn);
112     return false;
113 }
114
115 RawBuffer CKMService::ProcessControl(MessageBuffer &buffer) {
116     int command = 0;
117     uid_t user = 0;
118     ControlCommand cc;
119     Password newPass, oldPass;
120     Label smackLabel;
121
122     buffer.Deserialize(command);
123
124     LogDebug("Process control. Command: " << command);
125
126     cc = static_cast<ControlCommand>(command);
127
128     switch(cc) {
129     case ControlCommand::UNLOCK_USER_KEY:
130         buffer.Deserialize(user, newPass);
131         return m_logic->unlockUserKey(user, newPass);
132     case ControlCommand::LOCK_USER_KEY:
133         buffer.Deserialize(user);
134         return m_logic->lockUserKey(user);
135     case ControlCommand::REMOVE_USER_DATA:
136         buffer.Deserialize(user);
137         return m_logic->removeUserData(user);
138     case ControlCommand::CHANGE_USER_PASSWORD:
139         buffer.Deserialize(user, oldPass, newPass);
140         return m_logic->changeUserPassword(user, oldPass, newPass);
141     case ControlCommand::RESET_USER_PASSWORD:
142         buffer.Deserialize(user, newPass);
143         return m_logic->resetUserPassword(user, newPass);
144     case ControlCommand::REMOVE_APP_DATA:
145         buffer.Deserialize(smackLabel);
146         return m_logic->removeApplicationData(smackLabel);
147     case ControlCommand::UPDATE_CC_MODE:
148         return m_logic->updateCCMode();
149     case ControlCommand::SET_PERMISSION:
150     {
151         Name name;
152         Label label;
153         Label accessorLabel;
154         PermissionMask permissionMask = 0;
155
156         buffer.Deserialize(user, name, label, accessorLabel, permissionMask);
157
158         Credentials cred(user, label);
159         return m_logic->setPermission(
160             cred,
161             command,
162             0, // dummy
163             name,
164             label,
165             accessorLabel,
166             permissionMask);
167     }
168     default:
169         Throw(Exception::BrokenProtocol);
170     }
171 }
172
173 RawBuffer CKMService::ProcessStorage(Credentials &cred, MessageBuffer &buffer, bool allowed)
174 {
175     int command = 0;
176     int msgID = 0;
177     int tmpDataType = 0;
178     Name name;
179     Label label, accessorLabel;
180     std::string user;
181
182     buffer.Deserialize(command);
183     buffer.Deserialize(msgID);
184
185     // This is a workaround solution for locktype=None in Tizen 2.2.1
186     // When locktype is None, lockscreen app doesn't interfere with unlocking process.
187     // Therefor lockscreen app cannot notify unlock events to key-manager when locktype is None.
188     // So, to unlock user data when lock type is None, key-manager always try to unlock user data with null password.
189     // Even if the result is fail, it will be ignored.
190     Password nullPassword("");
191     m_logic->unlockUserKey(cred.clientUid, nullPassword);
192
193     LogDebug("Process storage. Command: " << command);
194
195     switch(static_cast<LogicCommand>(command)) {
196         case LogicCommand::SAVE:
197         {
198             RawBuffer rawData;
199             PolicySerializable policy;
200             buffer.Deserialize(tmpDataType, name, label, rawData, policy);
201
202             if (!allowed)
203                 return disallowed(command, msgID, static_cast<int>(DataType(tmpDataType)));
204
205             return m_logic->saveData(
206                 cred,
207                 msgID,
208                 name,
209                 label,
210                 rawData,
211                 DataType(tmpDataType),
212                 policy);
213         }
214         case LogicCommand::SAVE_PKCS12:
215         {
216             RawBuffer rawData;
217             PKCS12Serializable pkcs;
218             PolicySerializable keyPolicy, certPolicy;
219             buffer.Deserialize(name, label, pkcs, keyPolicy, certPolicy);
220
221             if (!allowed)
222                 return disallowed(command, msgID);
223
224             return m_logic->savePKCS12(
225                 cred,
226                 msgID,
227                 name,
228                 label,
229                 pkcs,
230                 keyPolicy,
231                 certPolicy);
232         }
233         case LogicCommand::REMOVE:
234         {
235             buffer.Deserialize(name, label);
236
237             if (!allowed)
238                 return disallowed(command, msgID);
239
240             return m_logic->removeData(
241                 cred,
242                 msgID,
243                 name,
244                 label);
245         }
246         case LogicCommand::GET:
247         {
248             Password password;
249             buffer.Deserialize(tmpDataType, name, label, password);
250
251             if (!allowed)
252                 return disallowed(command,
253                                   msgID,
254                                   static_cast<int>(DataType(tmpDataType)),
255                                   RawBuffer());
256
257             return m_logic->getData(
258                 cred,
259                 msgID,
260                 DataType(tmpDataType),
261                 name,
262                 label,
263                 password);
264         }
265         case LogicCommand::GET_PKCS12:
266         {
267             Password passKey;
268             Password passCert;
269             buffer.Deserialize(name,
270                                label,
271                                passKey,
272                                passCert);
273
274             if (!allowed)
275                 return disallowed(command, msgID, PKCS12Serializable());
276
277             return m_logic->getPKCS12(
278                 cred,
279                 msgID,
280                 name,
281                 label,
282                 passKey,
283                 passCert);
284         }
285         case LogicCommand::GET_LIST:
286         {
287             buffer.Deserialize(tmpDataType);
288
289             if (!allowed)
290                 return disallowed(command,
291                                   msgID,
292                                   static_cast<int>(DataType(tmpDataType)),
293                                   LabelNameVector());
294
295             return m_logic->getDataList(
296                 cred,
297                 msgID,
298                 DataType(tmpDataType));
299         }
300         case LogicCommand::CREATE_KEY_AES:
301         {
302             int size = 0;
303             Name keyName;
304             Label keyLabel;
305             PolicySerializable policyKey;
306             buffer.Deserialize(size,
307                                policyKey,
308                                keyName,
309                                keyLabel);
310
311             if (!allowed)
312                 return disallowed(command, msgID);
313
314             return m_logic->createKeyAES(
315                 cred,
316                 msgID,
317                 size,
318                 keyName,
319                 keyLabel,
320                 policyKey);
321         }
322         case LogicCommand::CREATE_KEY_PAIR:
323         {
324             CryptoAlgorithmSerializable keyGenAlgorithm;
325             Name privateKeyName;
326             Label privateKeyLabel;
327             Name publicKeyName;
328             Label publicKeyLabel;
329             PolicySerializable policyPrivateKey;
330             PolicySerializable policyPublicKey;
331             buffer.Deserialize(keyGenAlgorithm,
332                                policyPrivateKey,
333                                policyPublicKey,
334                                privateKeyName,
335                                privateKeyLabel,
336                                publicKeyName,
337                                publicKeyLabel);
338
339             if (!allowed)
340                 return disallowed(command, msgID);
341
342             return m_logic->createKeyPair(
343                 cred,
344                 msgID,
345                 keyGenAlgorithm,
346                 privateKeyName,
347                 privateKeyLabel,
348                 publicKeyName,
349                 publicKeyLabel,
350                 policyPrivateKey,
351                 policyPublicKey);
352         }
353         case LogicCommand::GET_CHAIN_CERT:
354         {
355             RawBuffer certificate;
356             RawBufferVector untrustedVector;
357             RawBufferVector trustedVector;
358             bool systemCerts = false;
359             buffer.Deserialize(certificate, untrustedVector, trustedVector, systemCerts);
360
361             if (!allowed)
362                 return disallowed(command, msgID, RawBufferVector());
363
364             return m_logic->getCertificateChain(
365                 cred,
366                 msgID,
367                 certificate,
368                 untrustedVector,
369                 trustedVector,
370                 systemCerts);
371         }
372         case LogicCommand::GET_CHAIN_ALIAS:
373         {
374             RawBuffer certificate;
375             LabelNameVector untrustedVector;
376             LabelNameVector trustedVector;
377             bool systemCerts = false;
378             buffer.Deserialize(certificate, untrustedVector, trustedVector, systemCerts);
379
380             if (!allowed)
381                 return disallowed(command, msgID, LabelNameVector());
382
383             return m_logic->getCertificateChain(
384                 cred,
385                 msgID,
386                 certificate,
387                 untrustedVector,
388                 trustedVector,
389                 systemCerts);
390         }
391         case LogicCommand::CREATE_SIGNATURE:
392         {
393             Password password;        // password for private_key
394             RawBuffer message;
395             int padding = 0, hash = 0;
396             buffer.Deserialize(name, label, password, message, hash, padding);
397
398             if (!allowed)
399                 return disallowed(command, msgID, RawBuffer());
400
401             return m_logic->createSignature(
402                   cred,
403                   msgID,
404                   name,
405                   label,
406                   password,           // password for private_key
407                   message,
408                   static_cast<HashAlgorithm>(hash),
409                   static_cast<RSAPaddingAlgorithm>(padding));
410         }
411         case LogicCommand::VERIFY_SIGNATURE:
412         {
413             Password password;           // password for public_key (optional)
414             RawBuffer message;
415             RawBuffer signature;
416             //HashAlgorithm hash;
417             //RSAPaddingAlgorithm padding;
418             int padding = 0, hash = 0;
419             buffer.Deserialize(name,
420                                label,
421                                password,
422                                message,
423                                signature,
424                                hash,
425                                padding);
426
427             if (!allowed)
428                 return disallowed(command, msgID);
429
430             return m_logic->verifySignature(
431                 cred,
432                 msgID,
433                 name,
434                 label,
435                 password,           // password for public_key (optional)
436                 message,
437                 signature,
438                 static_cast<const HashAlgorithm>(hash),
439                 static_cast<const RSAPaddingAlgorithm>(padding));
440         }
441         case LogicCommand::SET_PERMISSION:
442         {
443             PermissionMask permissionMask = 0;
444             buffer.Deserialize(name, label, accessorLabel, permissionMask);
445
446             if (!allowed)
447                 return disallowed(command, msgID);
448
449             return m_logic->setPermission(
450                 cred,
451                 command,
452                 msgID,
453                 name,
454                 label,
455                 accessorLabel,
456                 permissionMask);
457         }
458         default:
459             Throw(Exception::BrokenProtocol);
460     }
461 }
462
463 void CKMService::ProcessMessage(MsgKeyRequest msg)
464 {
465     Crypto::GKeyShPtr key;
466     int ret = m_logic->getKeyForService(msg.cred,
467                                         msg.name,
468                                         msg.label,
469                                         msg.password,
470                                         key);
471     MsgKeyResponse kResp(msg.id, key, ret);
472     try {
473         if (!m_commMgr->SendMessage(kResp))
474             LogError("No listener found"); // can't do much more
475     } catch (...) {
476         LogError("Uncaught exception in SendMessage. Check listeners.");
477     }
478 }
479
480 } // namespace CKM
481