Chromium Code Reviews| 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 NOTREACHED(); | |
| 45 return chromeos::RequestPinView::RequestPinErrorType::NONE; | |
| 46 } | |
| 47 | |
| 48 } // namespace | |
| 49 | |
| 50 namespace extensions { | |
| 51 | |
| 52 namespace { | |
| 53 | |
| 29 const char kErrorInvalidX509Cert[] = | 54 const char kErrorInvalidX509Cert[] = |
| 30 "Certificate is not a valid X.509 certificate."; | 55 "Certificate is not a valid X.509 certificate."; |
| 31 const char kErrorECDSANotSupported[] = "Key type ECDSA not supported."; | 56 const char kErrorECDSANotSupported[] = "Key type ECDSA not supported."; |
| 32 const char kErrorUnknownKeyType[] = "Key type unknown."; | 57 const char kErrorUnknownKeyType[] = "Key type unknown."; |
| 33 const char kErrorAborted[] = "Request was aborted."; | 58 const char kErrorAborted[] = "Request was aborted."; |
| 34 const char kErrorTimeout[] = "Request timed out, reply rejected."; | 59 const char kErrorTimeout[] = "Request timed out, reply rejected."; |
| 35 | 60 |
| 61 // requestPin constants. | |
| 62 const char kNoActiveDialog[] = "No active dialog from extension."; | |
| 63 const char kInvalidId[] = "Invalid signRequestId"; | |
| 64 const char kOtherFlowInProgress[] = "Other flow in progress"; | |
| 65 const char kPreviousDialogActive[] = "Previous request not finished"; | |
| 66 const char kNoUserInput[] = "No user input received"; | |
| 67 | |
| 36 } // namespace | 68 } // namespace |
| 37 | 69 |
| 70 const int api::certificate_provider::kMaxClosedDialogsPer10Mins = 2; | |
| 71 | |
| 38 CertificateProviderInternalReportCertificatesFunction:: | 72 CertificateProviderInternalReportCertificatesFunction:: |
| 39 ~CertificateProviderInternalReportCertificatesFunction() {} | 73 ~CertificateProviderInternalReportCertificatesFunction() {} |
| 40 | 74 |
| 41 ExtensionFunction::ResponseAction | 75 ExtensionFunction::ResponseAction |
| 42 CertificateProviderInternalReportCertificatesFunction::Run() { | 76 CertificateProviderInternalReportCertificatesFunction::Run() { |
| 43 std::unique_ptr<api_cpi::ReportCertificates::Params> params( | 77 std::unique_ptr<api_cpi::ReportCertificates::Params> params( |
| 44 api_cpi::ReportCertificates::Params::Create(*args_)); | 78 api_cpi::ReportCertificates::Params::Create(*args_)); |
| 45 EXTENSION_FUNCTION_VALIDATE(params); | 79 EXTENSION_FUNCTION_VALIDATE(params); |
| 46 | 80 |
| 47 chromeos::CertificateProviderService* const service = | 81 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); | 175 out_info->supported_hashes.push_back(net::SSLPrivateKey::Hash::SHA512); |
| 142 break; | 176 break; |
| 143 case api_cp::HASH_NONE: | 177 case api_cp::HASH_NONE: |
| 144 NOTREACHED(); | 178 NOTREACHED(); |
| 145 return false; | 179 return false; |
| 146 } | 180 } |
| 147 } | 181 } |
| 148 return true; | 182 return true; |
| 149 } | 183 } |
| 150 | 184 |
| 185 CertificateProviderStopPinRequestFunction:: | |
| 186 ~CertificateProviderStopPinRequestFunction() {} | |
| 187 | |
| 188 ExtensionFunction::ResponseAction | |
| 189 CertificateProviderStopPinRequestFunction::Run() { | |
| 190 std::unique_ptr<api_cp::RequestPin::Params> params( | |
| 191 api_cp::RequestPin::Params::Create(*args_)); | |
| 192 EXTENSION_FUNCTION_VALIDATE(params); | |
| 193 | |
| 194 chromeos::CertificateProviderService* const service = | |
| 195 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( | |
| 196 browser_context()); | |
| 197 DCHECK(service); | |
| 198 if (params->details.error_type == | |
| 199 api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_NONE) { | |
| 200 bool dialog_closed = | |
| 201 service->pin_dialog_manager()->CloseDialog(extension_id()); | |
| 202 if (!dialog_closed) { | |
| 203 // This might happen if the user closed the dialog while extension was | |
| 204 // processing the input. | |
| 205 return RespondNow(Error(kNoActiveDialog)); | |
| 206 } | |
| 207 | |
| 208 return RespondNow(NoArguments()); | |
| 209 } | |
| 210 | |
| 211 chromeos::RequestPinView::RequestPinErrorType error_type = | |
| 212 GetErrorTypeForView(params->details.error_type); | |
| 213 chromeos::PinDialogManager::StopPinRequestResponse update_response = | |
| 214 service->pin_dialog_manager()->UpdatePinDialog( | |
| 215 extension()->id(), error_type, | |
| 216 false, // Don't accept any input. | |
| 217 base::Bind(&CertificateProviderStopPinRequestFunction::DialogClosed, | |
| 218 this)); | |
| 219 switch (update_response) { | |
| 220 case chromeos::PinDialogManager::StopPinRequestResponse::NO_ACTIVE_DIALOG: | |
| 221 return RespondNow(Error(kNoActiveDialog)); | |
| 222 case chromeos::PinDialogManager::StopPinRequestResponse::NO_USER_INPUT: | |
| 223 return RespondNow(Error(kNoUserInput)); | |
|
Devlin
2016/11/29 21:09:03
Why is this an error? Can the extension not cance
igorcov
2016/11/30 15:32:38
The extension can cancel the flow without user inp
| |
| 224 case chromeos::PinDialogManager::StopPinRequestResponse::STOPPED: | |
| 225 return RespondLater(); | |
| 226 } | |
| 227 | |
| 228 NOTREACHED(); | |
| 229 return RespondLater(); | |
| 230 } | |
| 231 | |
| 232 void CertificateProviderStopPinRequestFunction::DialogClosed( | |
| 233 const base::string16& value) { | |
| 234 chromeos::CertificateProviderService* const service = | |
| 235 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( | |
| 236 browser_context()); | |
| 237 DCHECK(service); | |
| 238 | |
| 239 Respond(NoArguments()); | |
| 240 service->pin_dialog_manager()->OnPinDialogClosed(); | |
| 241 } | |
| 242 | |
| 243 CertificateProviderRequestPinFunction:: | |
| 244 ~CertificateProviderRequestPinFunction() {} | |
| 245 | |
| 246 bool CertificateProviderRequestPinFunction::ShouldSkipQuotaLimiting() const { | |
| 247 chromeos::CertificateProviderService* const service = | |
| 248 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( | |
| 249 browser_context()); | |
| 250 DCHECK(service); | |
| 251 | |
| 252 return !service->pin_dialog_manager()->LastPinDialogClosed(extension_id()); | |
| 253 } | |
| 254 | |
| 255 void CertificateProviderRequestPinFunction::GetQuotaLimitHeuristics( | |
| 256 extensions::QuotaLimitHeuristics* heuristics) const { | |
| 257 QuotaLimitHeuristic::Config short_limit_config = { | |
| 258 api::certificate_provider::kMaxClosedDialogsPer10Mins, | |
| 259 base::TimeDelta::FromMinutes(10)}; | |
| 260 heuristics->push_back(base::MakeUnique<QuotaService::TimedLimit>( | |
| 261 short_limit_config, new QuotaLimitHeuristic::SingletonBucketMapper(), | |
| 262 "MAX_PIN_DIALOGS_CLOSED_PER_10_MINUTES")); | |
| 263 } | |
| 264 | |
| 265 ExtensionFunction::ResponseAction CertificateProviderRequestPinFunction::Run() { | |
| 266 std::unique_ptr<api_cp::RequestPin::Params> params( | |
| 267 api_cp::RequestPin::Params::Create(*args_)); | |
| 268 EXTENSION_FUNCTION_VALIDATE(params); | |
| 269 | |
| 270 api_cp::PinRequestType pin_request_type = | |
| 271 params->details.request_type == | |
| 272 api_cp::PinRequestType::PIN_REQUEST_TYPE_NONE | |
| 273 ? api_cp::PinRequestType::PIN_REQUEST_TYPE_PIN | |
| 274 : params->details.request_type; | |
| 275 | |
| 276 chromeos::RequestPinView::RequestPinErrorType error_type = | |
| 277 GetErrorTypeForView(params->details.error_type); | |
| 278 | |
| 279 chromeos::RequestPinView::RequestPinCodeType code_type = | |
| 280 (pin_request_type == api_cp::PinRequestType::PIN_REQUEST_TYPE_PIN) | |
| 281 ? chromeos::RequestPinView::RequestPinCodeType::PIN | |
| 282 : chromeos::RequestPinView::RequestPinCodeType::PUK; | |
| 283 | |
| 284 chromeos::CertificateProviderService* const service = | |
| 285 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( | |
| 286 browser_context()); | |
| 287 DCHECK(service); | |
| 288 | |
| 289 int attempts_left = | |
| 290 params->details.attempts_left ? *params->details.attempts_left : -1; | |
| 291 chromeos::PinDialogManager::RequestPinResponse result = | |
| 292 service->pin_dialog_manager()->ShowPinDialog( | |
| 293 extension()->id(), extension()->name(), | |
| 294 params->details.sign_request_id, code_type, error_type, attempts_left, | |
| 295 base::Bind(&CertificateProviderRequestPinFunction::OnInputReceived, | |
| 296 this)); | |
| 297 switch (result) { | |
| 298 case chromeos::PinDialogManager::RequestPinResponse::SUCCESS: | |
| 299 return RespondLater(); | |
| 300 case chromeos::PinDialogManager::RequestPinResponse::INVALID_ID: | |
| 301 return RespondNow(Error(kInvalidId)); | |
| 302 case chromeos::PinDialogManager::RequestPinResponse::OTHER_FLOW_IN_PROGRESS: | |
| 303 return RespondNow(Error(kOtherFlowInProgress)); | |
| 304 case chromeos::PinDialogManager::RequestPinResponse:: | |
| 305 DIALOG_DISPLAYED_ALREADY: | |
| 306 return RespondNow(Error(kPreviousDialogActive)); | |
| 307 } | |
| 308 | |
| 309 NOTREACHED(); | |
| 310 return RespondNow(Error(kPreviousDialogActive)); | |
| 311 } | |
| 312 | |
| 313 void CertificateProviderRequestPinFunction::OnInputReceived( | |
| 314 const base::string16& value) { | |
| 315 std::unique_ptr<base::ListValue> create_results(new base::ListValue()); | |
| 316 chromeos::CertificateProviderService* const service = | |
| 317 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( | |
| 318 browser_context()); | |
| 319 DCHECK(service); | |
| 320 if (!value.empty()) { | |
| 321 api::certificate_provider::PinResponseDetails details; | |
| 322 details.user_input.reset(new std::string(value.begin(), value.end())); | |
| 323 create_results->Append(details.ToValue()); | |
| 324 } | |
| 325 | |
| 326 Respond(ArgumentList(std::move(create_results))); | |
| 327 if (!value.empty()) { | |
| 328 service->pin_dialog_manager()->OnPinDialogInput(); | |
|
Devlin
2016/11/29 21:09:03
Why is the API doing this instead of the dialog or
igorcov
2016/11/30 15:32:38
Moved to be notified by the dialog.
| |
| 329 } | |
| 330 } | |
| 331 | |
| 151 CertificateProviderInternalReportSignatureFunction:: | 332 CertificateProviderInternalReportSignatureFunction:: |
| 152 ~CertificateProviderInternalReportSignatureFunction() {} | 333 ~CertificateProviderInternalReportSignatureFunction() {} |
| 153 | 334 |
| 154 ExtensionFunction::ResponseAction | 335 ExtensionFunction::ResponseAction |
| 155 CertificateProviderInternalReportSignatureFunction::Run() { | 336 CertificateProviderInternalReportSignatureFunction::Run() { |
| 156 std::unique_ptr<api_cpi::ReportSignature::Params> params( | 337 std::unique_ptr<api_cpi::ReportSignature::Params> params( |
| 157 api_cpi::ReportSignature::Params::Create(*args_)); | 338 api_cpi::ReportSignature::Params::Create(*args_)); |
| 158 EXTENSION_FUNCTION_VALIDATE(params); | 339 EXTENSION_FUNCTION_VALIDATE(params); |
| 159 | 340 |
| 160 chromeos::CertificateProviderService* const service = | 341 chromeos::CertificateProviderService* const service = |
| 161 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( | 342 chromeos::CertificateProviderServiceFactory::GetForBrowserContext( |
| 162 browser_context()); | 343 browser_context()); |
| 163 DCHECK(service); | 344 DCHECK(service); |
| 164 | 345 |
| 165 std::vector<uint8_t> signature; | 346 std::vector<uint8_t> signature; |
| 166 // If an error occurred, |signature| will not be set. | 347 // If an error occurred, |signature| will not be set. |
| 167 if (params->signature) | 348 if (params->signature) |
| 168 signature.assign(params->signature->begin(), params->signature->end()); | 349 signature.assign(params->signature->begin(), params->signature->end()); |
| 169 | 350 |
| 170 service->ReplyToSignRequest(extension_id(), params->request_id, signature); | 351 service->ReplyToSignRequest(extension_id(), params->request_id, signature); |
| 171 return RespondNow(NoArguments()); | 352 return RespondNow(NoArguments()); |
| 172 } | 353 } |
| 173 | 354 |
| 174 } // namespace extensions | 355 } // namespace extensions |
| OLD | NEW |