blob: 4ab853d6aaeb8d0c2e10c4ac2b0007ddb9cedf44 [file] [log] [blame]
Yingdi Yu77627ab2015-07-21 16:13:49 -07001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2015 Regents of the University of California.
4 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
6 *
7 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
20 */
21
22#include "update-query-processor.hpp"
23#include "encoding/pib-encoding.hpp"
24#include "pib.hpp"
25
26#include <boost/lexical_cast.hpp>
27
28namespace ndn {
29namespace pib {
30
31using std::string;
32
33const size_t UpdateQueryProcessor::UPDATE_QUERY_LENGTH = 9;
34const Name UpdateQueryProcessor::PIB_PREFIX("/localhost/pib");
35
36UpdateQueryProcessor::UpdateQueryProcessor(PibDb& db, Pib& pib)
37 : m_db(db)
38 , m_pib(pib)
39{
40}
41
42std::pair<bool, Block>
43UpdateQueryProcessor::operator()(const Interest& interest)
44{
45 const Name& interestName = interest.getName();
46
47 // handle pib query: /localhost/pib/[UserName]/update/param/<signed_interest_related_components>
48 if (interestName.size() != UPDATE_QUERY_LENGTH) {
49 // malformed interest, discard
50 return std::make_pair(false, Block());
51 }
52
53 try {
54 UpdateParam param;
55 param.wireDecode(interestName.get(OFFSET_PARAM).blockFromValue());
56
57 SignatureInfo sigInfo;
58 sigInfo.wireDecode(interestName.get(OFFSET_SIG_INFO).blockFromValue());
59
60 // sigInfo must have KeyLocator.Name if the interest passed validation.
61 Name signerName;
62 signerName = sigInfo.getKeyLocator().getName();
63
64 switch (param.getEntityType()) {
65 case tlv::pib::User:
66 return processUpdateUserQuery(param, signerName);
67 case tlv::pib::Identity:
68 return processUpdateIdQuery(param, signerName);
69 case tlv::pib::PublicKey:
70 return processUpdateKeyQuery(param, signerName);
71 case tlv::pib::Certificate:
72 return processUpdateCertQuery(param, signerName);
73 default:
74 {
75 PibError error(ERR_WRONG_PARAM,
76 "entity type is not supported: " +
77 boost::lexical_cast<string>(param.getEntityType()));
78 return std::make_pair(true, error.wireEncode());
79 }
80 }
81 }
82 catch (const PibDb::Error& e) {
83 PibError error(ERR_INTERNAL_ERROR, e.what());
84 return std::make_pair(true, error.wireEncode());
85 }
86 catch (const tlv::Error& e) {
87 PibError error(ERR_WRONG_PARAM, "error in parsing param: " + string(e.what()));
88 return std::make_pair(true, error.wireEncode());
89 }
90}
91
92std::pair<bool, Block>
93UpdateQueryProcessor::processUpdateUserQuery(const UpdateParam& param, const Name& signerName)
94{
95 Name expectedId = m_db.getMgmtCertificate()->getPublicKeyName().getPrefix(-1);
96 Name targetId = param.getUser().getMgmtCert().getPublicKeyName().getPrefix(-1);
97 Name signerId = IdentityCertificate::certificateNameToPublicKeyName(signerName).getPrefix(-1);
98
99 if (expectedId == targetId && expectedId == signerId) {
100 m_db.updateMgmtCertificate(param.getUser().getMgmtCert());
101 m_pib.setMgmtCert(make_shared<IdentityCertificate>(param.getUser().getMgmtCert()));
102 return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
103 }
104
105 PibError error(ERR_WRONG_PARAM, "not allowed to update user");
106 return std::make_pair(true, error.wireEncode());
107}
108
109std::pair<bool, Block>
110UpdateQueryProcessor::processUpdateIdQuery(const UpdateParam& param, const Name& signerName)
111{
112 const Name& identity = param.getIdentity().getIdentity();
113 if (!isUpdateAllowed(TYPE_ID, identity, signerName, param.getDefaultOpt())) {
114 PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
115 return std::make_pair(true, error.wireEncode());
116 }
117
118 // add the identity
119 m_db.addIdentity(identity);
120
121 // set the identity as user default if it is requested.
122 const pib::DefaultOpt& defaultOpt = param.getDefaultOpt();
123 if (DEFAULT_OPT_USER_MASK & defaultOpt) {
124 m_db.setDefaultIdentity(identity);
125 }
126
127 return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
128}
129
130std::pair<bool, Block>
131UpdateQueryProcessor::processUpdateKeyQuery(const UpdateParam& param, const Name& signerName)
132{
133 const Name& keyName = param.getPublicKey().getKeyName();
134 if (!isUpdateAllowed(TYPE_KEY, keyName, signerName, param.getDefaultOpt())) {
135 PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
136 return std::make_pair(true, error.wireEncode());
137 }
138
139 Name identity = keyName.getPrefix(-1);
140
141 // add the key
142 m_db.addKey(keyName, param.getPublicKey().getPublicKey());
143
144 const pib::DefaultOpt& defaultOpt = param.getDefaultOpt();
145 if (DEFAULT_OPT_ID_MASK & defaultOpt) // set the key as identity default if requested.
146 m_db.setDefaultKeyNameOfIdentity(keyName);
147 if (DEFAULT_OPT_USER_MASK & defaultOpt) // set the identity as user default if requested.
148 m_db.setDefaultIdentity(identity);
149
150 return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
151}
152
153std::pair<bool, Block>
154UpdateQueryProcessor::processUpdateCertQuery(const UpdateParam& param, const Name& signerName)
155{
156 const IdentityCertificate& cert = param.getCertificate().getCertificate();
157 const Name& certName = cert.getName();
158 if (!isUpdateAllowed(TYPE_CERT, certName, signerName, param.getDefaultOpt())) {
159 PibError error(ERR_WRONG_SIGNER, "signer is not trusted for this command");
160 return std::make_pair(true, error.wireEncode());
161 }
162
163 const Name& keyName = cert.getPublicKeyName();
164 Name identity = keyName.getPrefix(-1);
165
166 // add certificate
167 m_db.addCertificate(cert);
168
169 const pib::DefaultOpt& defaultOpt = param.getDefaultOpt();
170 if (DEFAULT_OPT_KEY_MASK & defaultOpt) // set the cert as key default if requested.
171 m_db.setDefaultCertNameOfKey(certName);
172 if (DEFAULT_OPT_ID_MASK & defaultOpt) // set the key as identity default if requested.
173 m_db.setDefaultKeyNameOfIdentity(keyName);
174 if (DEFAULT_OPT_USER_MASK & defaultOpt) // set the identity as user default if requested.
175 m_db.setDefaultIdentity(identity);
176
177 return std::make_pair(true, PibError(ERR_SUCCESS).wireEncode());
178}
179
180bool
181UpdateQueryProcessor::isUpdateAllowed(const pib::Type targetType,
182 const Name& targetName,
183 const Name& signer,
184 const pib::DefaultOpt defaultOpt) const
185{
186 // Any identity with prefix /localhost/pib is reserved. Any operation with a targetName under
187 // that prefix will be rejected.
188 if (PIB_PREFIX.isPrefixOf(targetName))
189 return false;
190
191 // A request is wrong if
192 // 1) it wants to change the default setting of an identity, but the target is not key nor cert
193 // 2) it wants to change the default setting of a key, but the target is not cert
194 if ((defaultOpt == DEFAULT_OPT_ID && (targetType != TYPE_KEY && targetType != TYPE_CERT)) ||
195 (defaultOpt == DEFAULT_OPT_KEY && targetType != TYPE_CERT))
196 return false;
197
198
199 // Rules for other items:
200 //
201 // signer | adding privilege | default setting privilege
202 // ================+==========================+============================================
203 // local mgmt key | any id, key, and cert | the default id,
204 // | | the default key of any id,
205 // | | the default cert of any key of any id
206 // ----------------+--------------------------+--------------------------------------------
207 // default key of | any id, key, and cert | the default key of the id and its sub ids,
208 // an id | under the id's namespace | the default cert of any key of the id
209 // | | and its sub ids
210 // ----------------+--------------------------+--------------------------------------------
211 // non-default key | any cert of the key | the default cert of the key
212 // of an id
213
214 const Name& signerKeyName = IdentityCertificate::certificateNameToPublicKeyName(signer);
215 const Name& signerId = signerKeyName.getPrefix(-1);
216
217 bool hasSignerDefaultKey = true;
218 Name signerDefaultKeyName;
219 try {
220 signerDefaultKeyName = m_db.getDefaultKeyNameOfIdentity(signerId);
221 }
222 catch (PibDb::Error&) {
223 hasSignerDefaultKey = false;
224 }
225
226 Name mgmtCertName;
227 try {
228 mgmtCertName = m_db.getMgmtCertificate()->getName().getPrefix(-1);
229 }
230 catch (PibDb::Error&) {
231 return false;
232 }
233
234 if (signer == mgmtCertName) {
235 // signer is current management key, anything is allowed.
236 return true;
237 }
238 else if (hasSignerDefaultKey && signerDefaultKeyName == signerKeyName) {
239 // signer is an identity's default key
240 if (!signerId.isPrefixOf(targetName))
241 return false;
242
243 // check default setting
244 // user default setting is not allowed
245 if (defaultOpt == DEFAULT_OPT_USER)
246 return false;
247 else
248 return true;
249 }
250 else {
251 // non-default key
252 if (targetType != TYPE_CERT)
253 return false;
254
255 // check if it is for the key's cert
256 if (IdentityCertificate::certificateNameToPublicKeyName(targetName) != signerKeyName)
257 return false;
258
259 if (defaultOpt == DEFAULT_OPT_USER || defaultOpt == DEFAULT_OPT_ID)
260 return false;
261 else
262 return true;
263 }
264}
265
266} // namespace pib
267} // namespace ndn