OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/certificate_provider/certificate_provide
r_api.h" | 5 #include "chrome/browser/extensions/api/certificate_provider/certificate_provide
r_api.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_serv
ice.h" | 14 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_serv
ice.h" |
15 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_serv
ice_factory.h" | 15 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_serv
ice_factory.h" |
16 #include "chrome/common/extensions/api/certificate_provider.h" | 16 #include "chrome/common/extensions/api/certificate_provider.h" |
17 #include "chrome/common/extensions/api/certificate_provider_internal.h" | 17 #include "chrome/common/extensions/api/certificate_provider_internal.h" |
18 #include "content/public/common/console_message_level.h" | 18 #include "content/public/common/console_message_level.h" |
19 #include "net/cert/x509_certificate.h" | 19 #include "net/cert/x509_certificate.h" |
20 #include "net/ssl/ssl_private_key.h" | 20 #include "net/ssl/ssl_private_key.h" |
21 | 21 |
22 namespace extensions { | 22 namespace api_cp = extensions::api::certificate_provider; |
23 | 23 namespace api_cpi = extensions::api::certificate_provider_internal; |
24 namespace api_cp = api::certificate_provider; | |
25 namespace api_cpi = api::certificate_provider_internal; | |
26 | 24 |
27 namespace { | 25 namespace { |
28 | 26 |
| 27 chromeos::RequestPinView::RequestPinErrorType GetErrorTypeForView( |
| 28 api_cp::PinRequestErrorType error_type) { |
| 29 switch (error_type) { |
| 30 case api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_INVALID_PIN: |
| 31 return chromeos::RequestPinView::RequestPinErrorType::INVALID_PIN; |
| 32 case api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_INVALID_PUK: |
| 33 return chromeos::RequestPinView::RequestPinErrorType::INVALID_PUK; |
| 34 case api_cp::PinRequestErrorType:: |
| 35 PIN_REQUEST_ERROR_TYPE_MAX_ATTEMPTS_EXCEEDED: |
| 36 return chromeos::RequestPinView::RequestPinErrorType:: |
| 37 MAX_ATTEMPTS_EXCEEDED; |
| 38 case api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_UNKNOWN_ERROR: |
| 39 return chromeos::RequestPinView::RequestPinErrorType::UNKNOWN_ERROR; |
| 40 case api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_NONE: |
| 41 return chromeos::RequestPinView::RequestPinErrorType::NONE; |
| 42 } |
| 43 } |
| 44 |
| 45 } // namespace |
| 46 |
| 47 namespace extensions { |
| 48 |
| 49 namespace { |
| 50 |
29 const char kErrorInvalidX509Cert[] = | 51 const char kErrorInvalidX509Cert[] = |
30 "Certificate is not a valid X.509 certificate."; | 52 "Certificate is not a valid X.509 certificate."; |
31 const char kErrorECDSANotSupported[] = "Key type ECDSA not supported."; | 53 const char kErrorECDSANotSupported[] = "Key type ECDSA not supported."; |
32 const char kErrorUnknownKeyType[] = "Key type unknown."; | 54 const char kErrorUnknownKeyType[] = "Key type unknown."; |
33 const char kErrorAborted[] = "Request was aborted."; | 55 const char kErrorAborted[] = "Request was aborted."; |
34 const char kErrorTimeout[] = "Request timed out, reply rejected."; | 56 const char kErrorTimeout[] = "Request timed out, reply rejected."; |
35 | 57 |
| 58 // requestPin constants. |
| 59 const char kNoActiveDialog[] = "No active dialog from extension."; |
| 60 const char kInvalidId[] = "Invalid signRequestId"; |
| 61 const char kOtherFlowInProgress[] = "Other flow in progress"; |
| 62 const char kPreviousDialogActive[] = "Previous request not finished"; |
| 63 |
36 } // namespace | 64 } // namespace |
37 | 65 |
| 66 const int api::certificate_provider::kMaxClosedDialogsPer10Mins = 2; |
| 67 |
38 CertificateProviderInternalReportCertificatesFunction:: | 68 CertificateProviderInternalReportCertificatesFunction:: |
39 ~CertificateProviderInternalReportCertificatesFunction() {} | 69 ~CertificateProviderInternalReportCertificatesFunction() {} |
40 | 70 |
41 ExtensionFunction::ResponseAction | 71 ExtensionFunction::ResponseAction |
42 CertificateProviderInternalReportCertificatesFunction::Run() { | 72 CertificateProviderInternalReportCertificatesFunction::Run() { |
43 std::unique_ptr<api_cpi::ReportCertificates::Params> params( | 73 std::unique_ptr<api_cpi::ReportCertificates::Params> params( |
44 api_cpi::ReportCertificates::Params::Create(*args_)); | 74 api_cpi::ReportCertificates::Params::Create(*args_)); |
45 EXTENSION_FUNCTION_VALIDATE(params); | 75 EXTENSION_FUNCTION_VALIDATE(params); |
46 | 76 |
47 chromeos::CertificateProviderService* const service = | 77 chromeos::CertificateProviderService* const service = |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 out_info->supported_hashes.push_back(net::SSLPrivateKey::Hash::SHA512); | 171 out_info->supported_hashes.push_back(net::SSLPrivateKey::Hash::SHA512); |
142 break; | 172 break; |
143 case api_cp::HASH_NONE: | 173 case api_cp::HASH_NONE: |
144 NOTREACHED(); | 174 NOTREACHED(); |
145 return false; | 175 return false; |
146 } | 176 } |
147 } | 177 } |
148 return true; | 178 return true; |
149 } | 179 } |
150 | 180 |
| 181 CertificateProviderStopPinRequestFunction:: |
| 182 ~CertificateProviderStopPinRequestFunction() {} |
| 183 |
| 184 ExtensionFunction::ResponseAction |
| 185 CertificateProviderStopPinRequestFunction::Run() { |
| 186 std::unique_ptr<api_cp::RequestPin::Params> params( |
| 187 api_cp::RequestPin::Params::Create(*args_)); |
| 188 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 189 |
| 190 chromeos::CertificateProviderService* const service = |
| 191 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( |
| 192 browser_context()); |
| 193 DCHECK(service); |
| 194 if (params->details.error_type == |
| 195 api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_NONE) { |
| 196 bool dialog_closed = |
| 197 service->pin_dialog_manager()->CloseDialog(extension_id()); |
| 198 if (!dialog_closed) { |
| 199 // This might happen if the user closed the dialog while extension was |
| 200 // processing the input. |
| 201 LOG(ERROR) << "Wrong extension requesting to close the dialog"; |
| 202 return RespondNow(Error(kNoActiveDialog)); |
| 203 } |
| 204 |
| 205 std::unique_ptr<base::ListValue> create_results(new base::ListValue()); |
| 206 return RespondNow(ArgumentList(std::move(create_results))); |
| 207 } |
| 208 |
| 209 chromeos::RequestPinView::RequestPinErrorType error_type = |
| 210 GetErrorTypeForView(params->details.error_type); |
| 211 bool success = service->pin_dialog_manager()->UpdatePinDialog( |
| 212 extension()->id(), error_type, |
| 213 false, // Don't accept any input. |
| 214 base::Bind(&CertificateProviderStopPinRequestFunction::DialogClosed, |
| 215 this)); |
| 216 if (!success) { |
| 217 return RespondNow(Error(kNoActiveDialog)); |
| 218 } |
| 219 |
| 220 return RespondLater(); |
| 221 } |
| 222 |
| 223 void CertificateProviderStopPinRequestFunction::DialogClosed( |
| 224 const base::string16& value) { |
| 225 std::unique_ptr<base::ListValue> create_results(new base::ListValue()); |
| 226 chromeos::CertificateProviderService* const service = |
| 227 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( |
| 228 browser_context()); |
| 229 DCHECK(service); |
| 230 |
| 231 Respond(ArgumentList(std::move(create_results))); |
| 232 service->pin_dialog_manager()->OnPinDialogClosed(); |
| 233 } |
| 234 |
| 235 CertificateProviderRequestPinFunction:: |
| 236 ~CertificateProviderRequestPinFunction() {} |
| 237 |
| 238 bool CertificateProviderRequestPinFunction::ShouldSkipQuotaLimiting() const { |
| 239 chromeos::CertificateProviderService* const service = |
| 240 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( |
| 241 browser_context()); |
| 242 DCHECK(service); |
| 243 |
| 244 return !service->pin_dialog_manager()->LastPinDialogClosed(extension_id()); |
| 245 } |
| 246 |
| 247 void CertificateProviderRequestPinFunction::GetQuotaLimitHeuristics( |
| 248 extensions::QuotaLimitHeuristics* heuristics) const { |
| 249 QuotaLimitHeuristic::Config short_limit_config = { |
| 250 api::certificate_provider::kMaxClosedDialogsPer10Mins, |
| 251 base::TimeDelta::FromMinutes(1)}; |
| 252 heuristics->push_back(new QuotaService::TimedLimit( |
| 253 short_limit_config, new QuotaLimitHeuristic::SingletonBucketMapper(), |
| 254 "MAX_PIN_DIALOGS_CLOSED_PER_10_MINUTES")); |
| 255 } |
| 256 |
| 257 ExtensionFunction::ResponseAction CertificateProviderRequestPinFunction::Run() { |
| 258 std::unique_ptr<api_cp::RequestPin::Params> params( |
| 259 api_cp::RequestPin::Params::Create(*args_)); |
| 260 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 261 |
| 262 api_cp::PinRequestType pin_request_type = |
| 263 (params->details.request_type == |
| 264 api_cp::PinRequestType::PIN_REQUEST_TYPE_NONE) |
| 265 ? api_cp::PinRequestType::PIN_REQUEST_TYPE_PIN |
| 266 : params->details.request_type; |
| 267 |
| 268 chromeos::RequestPinView::RequestPinErrorType error_type = |
| 269 GetErrorTypeForView(params->details.error_type); |
| 270 |
| 271 chromeos::RequestPinView::RequestPinCodeType code_type = |
| 272 (pin_request_type == api_cp::PinRequestType::PIN_REQUEST_TYPE_PIN) |
| 273 ? chromeos::RequestPinView::RequestPinCodeType::PIN |
| 274 : chromeos::RequestPinView::RequestPinCodeType::PUK; |
| 275 |
| 276 chromeos::CertificateProviderService* const service = |
| 277 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( |
| 278 browser_context()); |
| 279 DCHECK(service); |
| 280 |
| 281 int attempts_left = |
| 282 params->details.attempts_left ? *params->details.attempts_left.get() : -1; |
| 283 chromeos::PinDialogManager::RequestPinResponse result = |
| 284 service->pin_dialog_manager()->ShowPinDialog( |
| 285 extension()->id(), extension()->name(), |
| 286 params->details.sign_request_id, code_type, error_type, attempts_left, |
| 287 base::Bind(&CertificateProviderRequestPinFunction::OnInputReceived, |
| 288 this)); |
| 289 switch (result) { |
| 290 case chromeos::PinDialogManager::RequestPinResponse::SUCCESS: |
| 291 return RespondLater(); |
| 292 case chromeos::PinDialogManager::RequestPinResponse::INVALID_ID: |
| 293 return RespondNow(Error(kInvalidId)); |
| 294 case chromeos::PinDialogManager::RequestPinResponse::OTHER_FLOW_IN_PROGRESS: |
| 295 return RespondNow(Error(kOtherFlowInProgress)); |
| 296 case chromeos::PinDialogManager::RequestPinResponse:: |
| 297 DIALOG_DISPLAYED_ALREADY: |
| 298 return RespondNow(Error(kPreviousDialogActive)); |
| 299 } |
| 300 } |
| 301 |
| 302 void CertificateProviderRequestPinFunction::OnInputReceived( |
| 303 const base::string16& value) { |
| 304 std::unique_ptr<base::ListValue> create_results(new base::ListValue()); |
| 305 chromeos::CertificateProviderService* const service = |
| 306 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( |
| 307 browser_context()); |
| 308 DCHECK(service); |
| 309 if (!value.empty()) { |
| 310 api::certificate_provider::PinResponseDetails details; |
| 311 details.user_input.reset(new std::string(value.begin(), value.end())); |
| 312 create_results->Append(details.ToValue()); |
| 313 } |
| 314 |
| 315 Respond(ArgumentList(std::move(create_results))); |
| 316 if (!value.empty()) { |
| 317 service->pin_dialog_manager()->OnPinDialogInput(); |
| 318 } |
| 319 } |
| 320 |
151 CertificateProviderInternalReportSignatureFunction:: | 321 CertificateProviderInternalReportSignatureFunction:: |
152 ~CertificateProviderInternalReportSignatureFunction() {} | 322 ~CertificateProviderInternalReportSignatureFunction() {} |
153 | 323 |
154 ExtensionFunction::ResponseAction | 324 ExtensionFunction::ResponseAction |
155 CertificateProviderInternalReportSignatureFunction::Run() { | 325 CertificateProviderInternalReportSignatureFunction::Run() { |
156 std::unique_ptr<api_cpi::ReportSignature::Params> params( | 326 std::unique_ptr<api_cpi::ReportSignature::Params> params( |
157 api_cpi::ReportSignature::Params::Create(*args_)); | 327 api_cpi::ReportSignature::Params::Create(*args_)); |
158 EXTENSION_FUNCTION_VALIDATE(params); | 328 EXTENSION_FUNCTION_VALIDATE(params); |
159 | 329 |
160 chromeos::CertificateProviderService* const service = | 330 chromeos::CertificateProviderService* const service = |
161 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( | 331 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( |
162 browser_context()); | 332 browser_context()); |
163 DCHECK(service); | 333 DCHECK(service); |
164 | 334 |
165 std::vector<uint8_t> signature; | 335 std::vector<uint8_t> signature; |
166 // If an error occurred, |signature| will not be set. | 336 // If an error occurred, |signature| will not be set. |
167 if (params->signature) | 337 if (params->signature) |
168 signature.assign(params->signature->begin(), params->signature->end()); | 338 signature.assign(params->signature->begin(), params->signature->end()); |
169 | 339 |
170 service->ReplyToSignRequest(extension_id(), params->request_id, signature); | 340 service->ReplyToSignRequest(extension_id(), params->request_id, signature); |
171 return RespondNow(NoArguments()); | 341 return RespondNow(NoArguments()); |
172 } | 342 } |
173 | 343 |
174 } // namespace extensions | 344 } // namespace extensions |
OLD | NEW |