1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/browser/api/cast_channel/cast_auth_util.h"
7 #include "base/logging.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/stringprintf.h"
10 #include "extensions/browser/api/cast_channel/cast_message_util.h"
11 #include "extensions/common/api/cast_channel/cast_channel.pb.h"
13 namespace extensions
{
15 namespace cast_channel
{
18 const char* const kParseErrorPrefix
= "Failed to parse auth message: ";
20 const unsigned char kAudioOnlyPolicy
[] =
21 {0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xD6, 0x79, 0x02, 0x05, 0x02};
23 // Extracts an embedded DeviceAuthMessage payload from an auth challenge reply
25 AuthResult
ParseAuthMessage(const CastMessage
& challenge_reply
,
26 DeviceAuthMessage
* auth_message
) {
27 if (challenge_reply
.payload_type() != CastMessage_PayloadType_BINARY
) {
28 return AuthResult::CreateWithParseError(
29 "Wrong payload type in challenge reply",
30 AuthResult::ERROR_WRONG_PAYLOAD_TYPE
);
32 if (!challenge_reply
.has_payload_binary()) {
33 return AuthResult::CreateWithParseError(
34 "Payload type is binary but payload_binary field not set",
35 AuthResult::ERROR_NO_PAYLOAD
);
37 if (!auth_message
->ParseFromString(challenge_reply
.payload_binary())) {
38 return AuthResult::CreateWithParseError(
39 "Cannot parse binary payload into DeviceAuthMessage",
40 AuthResult::ERROR_PAYLOAD_PARSING_FAILED
);
43 VLOG(1) << "Auth message: " << AuthMessageToString(*auth_message
);
45 if (auth_message
->has_error()) {
46 return AuthResult::CreateWithParseError(
47 "Auth message error: " +
48 base::IntToString(auth_message
->error().error_type()),
49 AuthResult::ERROR_MESSAGE_ERROR
);
51 if (!auth_message
->has_response()) {
52 return AuthResult::CreateWithParseError(
53 "Auth message has no response field", AuthResult::ERROR_NO_RESPONSE
);
60 AuthResult::AuthResult()
61 : error_type(ERROR_NONE
), nss_error_code(0), channel_policies(POLICY_NONE
) {
64 AuthResult::~AuthResult() {
68 AuthResult
AuthResult::CreateWithParseError(const std::string
& error_message
,
69 ErrorType error_type
) {
70 return AuthResult(kParseErrorPrefix
+ error_message
, error_type
, 0);
74 AuthResult
AuthResult::CreateWithNSSError(const std::string
& error_message
,
77 return AuthResult(error_message
, error_type
, nss_error_code
);
80 AuthResult::AuthResult(const std::string
& error_message
,
83 : error_message(error_message
),
84 error_type(error_type
),
85 nss_error_code(nss_error_code
) {
88 AuthResult
AuthenticateChallengeReply(const CastMessage
& challenge_reply
,
89 const std::string
& peer_cert
) {
90 if (peer_cert
.empty()) {
91 AuthResult result
= AuthResult::CreateWithParseError(
92 "Peer cert was empty.", AuthResult::ERROR_PEER_CERT_EMPTY
);
96 DeviceAuthMessage auth_message
;
97 AuthResult result
= ParseAuthMessage(challenge_reply
, &auth_message
);
98 if (!result
.success()) {
102 const AuthResponse
& response
= auth_message
.response();
103 result
= VerifyCredentials(response
, peer_cert
);
104 if (!result
.success()) {
108 if (response
.client_auth_certificate().find(reinterpret_cast<const char*>(
109 kAudioOnlyPolicy
)) != std::string::npos
) {
110 result
.channel_policies
|= AuthResult::POLICY_AUDIO_ONLY
;
116 } // namespace cast_channel
117 } // namespace core_api
118 } // namespace extensions