Home | History | Annotate | Download | only in network
      1 // Copyright (c) 2012 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.
      4 
      5 #include "chromeos/network/network_ui_data.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/values.h"
      9 #include "chromeos/network/onc/onc_signature.h"
     10 
     11 namespace chromeos {
     12 
     13 // Top-level UI data dictionary keys.
     14 const char NetworkUIData::kKeyONCSource[] = "onc_source";
     15 const char NetworkUIData::kKeyCertificatePattern[] = "certificate_pattern";
     16 const char NetworkUIData::kKeyCertificateType[] = "certificate_type";
     17 const char NetworkUIData::kKeyUserSettings[] = "user_settings";
     18 const char NetworkUIData::kONCSourceUserImport[] = "user_import";
     19 const char NetworkUIData::kONCSourceDevicePolicy[] = "device_policy";
     20 const char NetworkUIData::kONCSourceUserPolicy[] = "user_policy";
     21 
     22 namespace {
     23 
     24 template <typename Enum>
     25 struct StringEnumEntry {
     26   const char* string;
     27   Enum enum_value;
     28 };
     29 
     30 const StringEnumEntry< ::onc::ONCSource> kONCSourceTable[] = {
     31   { NetworkUIData::kONCSourceUserImport, ::onc::ONC_SOURCE_USER_IMPORT },
     32   { NetworkUIData::kONCSourceDevicePolicy, ::onc::ONC_SOURCE_DEVICE_POLICY },
     33   { NetworkUIData::kONCSourceUserPolicy, ::onc::ONC_SOURCE_USER_POLICY }
     34 };
     35 
     36 const StringEnumEntry<ClientCertType> kClientCertTable[] = {
     37   { "none", CLIENT_CERT_TYPE_NONE },
     38   { "pattern", CLIENT_CERT_TYPE_PATTERN },
     39   { "ref", CLIENT_CERT_TYPE_REF }
     40 };
     41 
     42 // Converts |enum_value| to the corresponding string according to |table|. If no
     43 // enum value of the table matches (which can only occur if incorrect casting
     44 // was used to obtain |enum_value|), returns an empty string instead.
     45 template <typename Enum, int N>
     46 std::string EnumToString(const StringEnumEntry<Enum>(& table)[N],
     47                          Enum enum_value) {
     48   for (int i = 0; i < N; ++i) {
     49     if (table[i].enum_value == enum_value)
     50       return table[i].string;
     51   }
     52   return std::string();
     53 }
     54 
     55 // Converts |str| to the corresponding enum value according to |table|. If no
     56 // string of the table matches, returns |fallback| instead.
     57 template<typename Enum, int N>
     58 Enum StringToEnum(const StringEnumEntry<Enum>(& table)[N],
     59                   const std::string& str,
     60                   Enum fallback) {
     61   for (int i = 0; i < N; ++i) {
     62     if (table[i].string == str)
     63       return table[i].enum_value;
     64   }
     65   return fallback;
     66 }
     67 
     68 }  // namespace
     69 
     70 NetworkUIData::NetworkUIData()
     71     : onc_source_(::onc::ONC_SOURCE_NONE),
     72       certificate_type_(CLIENT_CERT_TYPE_NONE) {
     73 }
     74 
     75 NetworkUIData::NetworkUIData(const NetworkUIData& other) {
     76   *this = other;
     77 }
     78 
     79 NetworkUIData& NetworkUIData::operator=(const NetworkUIData& other) {
     80   certificate_pattern_ = other.certificate_pattern_;
     81   onc_source_ = other.onc_source_;
     82   certificate_type_ = other.certificate_type_;
     83   if (other.user_settings_)
     84     user_settings_.reset(other.user_settings_->DeepCopy());
     85   policy_guid_ = other.policy_guid_;
     86   return *this;
     87 }
     88 
     89 NetworkUIData::NetworkUIData(const base::DictionaryValue& dict) {
     90   std::string source;
     91   dict.GetString(kKeyONCSource, &source);
     92   onc_source_ = StringToEnum(kONCSourceTable, source, ::onc::ONC_SOURCE_NONE);
     93 
     94   std::string type_string;
     95   dict.GetString(kKeyCertificateType, &type_string);
     96   certificate_type_ =
     97       StringToEnum(kClientCertTable, type_string, CLIENT_CERT_TYPE_NONE);
     98 
     99   if (certificate_type_ == CLIENT_CERT_TYPE_PATTERN) {
    100     const base::DictionaryValue* cert_dict = NULL;
    101     dict.GetDictionary(kKeyCertificatePattern, &cert_dict);
    102     if (cert_dict)
    103       certificate_pattern_.CopyFromDictionary(*cert_dict);
    104     if (certificate_pattern_.Empty()) {
    105       // This case may occur if UIData from an older CrOS version is read.
    106       LOG(WARNING) << "Couldn't parse a valid certificate pattern.";
    107       certificate_type_ = CLIENT_CERT_TYPE_NONE;
    108     }
    109   }
    110 
    111   const base::DictionaryValue* user_settings = NULL;
    112   if (dict.GetDictionary(kKeyUserSettings, &user_settings))
    113     user_settings_.reset(user_settings->DeepCopy());
    114 }
    115 
    116 NetworkUIData::~NetworkUIData() {
    117 }
    118 
    119 void NetworkUIData::set_user_settings(scoped_ptr<base::DictionaryValue> dict) {
    120   user_settings_ = dict.Pass();
    121 }
    122 
    123 std::string NetworkUIData::GetONCSourceAsString() const {
    124   return EnumToString(kONCSourceTable, onc_source_);
    125 }
    126 
    127 void NetworkUIData::FillDictionary(base::DictionaryValue* dict) const {
    128   dict->Clear();
    129 
    130   std::string source_string = GetONCSourceAsString();
    131   if (!source_string.empty())
    132     dict->SetString(kKeyONCSource, source_string);
    133 
    134   if (certificate_type_ != CLIENT_CERT_TYPE_NONE) {
    135     std::string type_string = EnumToString(kClientCertTable, certificate_type_);
    136     dict->SetString(kKeyCertificateType, type_string);
    137 
    138     if (certificate_type_ == CLIENT_CERT_TYPE_PATTERN &&
    139         !certificate_pattern_.Empty()) {
    140       dict->Set(kKeyCertificatePattern,
    141                 certificate_pattern_.CreateAsDictionary());
    142     }
    143   }
    144   if (user_settings_)
    145     dict->SetWithoutPathExpansion(kKeyUserSettings,
    146                                   user_settings_->DeepCopy());
    147 }
    148 
    149 namespace {
    150 
    151 void TranslateClientCertType(const std::string& client_cert_type,
    152                              NetworkUIData* ui_data) {
    153   using namespace ::onc::certificate;
    154   ClientCertType type;
    155   if (client_cert_type == kNone) {
    156     type = CLIENT_CERT_TYPE_NONE;
    157   } else if (client_cert_type == kRef) {
    158     type = CLIENT_CERT_TYPE_REF;
    159   } else if (client_cert_type == kPattern) {
    160     type = CLIENT_CERT_TYPE_PATTERN;
    161   } else {
    162     type = CLIENT_CERT_TYPE_NONE;
    163     NOTREACHED();
    164   }
    165 
    166   ui_data->set_certificate_type(type);
    167 }
    168 
    169 void TranslateCertificatePattern(const base::DictionaryValue& onc_object,
    170                                  NetworkUIData* ui_data) {
    171   CertificatePattern pattern;
    172   bool success = pattern.CopyFromDictionary(onc_object);
    173   DCHECK(success);
    174   ui_data->set_certificate_pattern(pattern);
    175 }
    176 
    177 void TranslateEAP(const base::DictionaryValue& eap,
    178                   NetworkUIData* ui_data) {
    179   std::string client_cert_type;
    180   if (eap.GetStringWithoutPathExpansion(::onc::eap::kClientCertType,
    181                                         &client_cert_type)) {
    182     TranslateClientCertType(client_cert_type, ui_data);
    183   }
    184 }
    185 
    186 void TranslateIPsec(const base::DictionaryValue& ipsec,
    187                     NetworkUIData* ui_data) {
    188   std::string client_cert_type;
    189   if (ipsec.GetStringWithoutPathExpansion(::onc::vpn::kClientCertType,
    190                                           &client_cert_type)) {
    191     TranslateClientCertType(client_cert_type, ui_data);
    192   }
    193 }
    194 
    195 void TranslateOpenVPN(const base::DictionaryValue& openvpn,
    196                       NetworkUIData* ui_data) {
    197   std::string client_cert_type;
    198   if (openvpn.GetStringWithoutPathExpansion(::onc::vpn::kClientCertType,
    199                                             &client_cert_type)) {
    200     TranslateClientCertType(client_cert_type, ui_data);
    201   }
    202 }
    203 
    204 void TranslateONCHierarchy(const onc::OncValueSignature& signature,
    205                            const base::DictionaryValue& onc_object,
    206                            NetworkUIData* ui_data) {
    207   if (&signature == &onc::kCertificatePatternSignature)
    208     TranslateCertificatePattern(onc_object, ui_data);
    209   else if (&signature == &onc::kEAPSignature)
    210     TranslateEAP(onc_object, ui_data);
    211   else if (&signature == &onc::kIPsecSignature)
    212     TranslateIPsec(onc_object, ui_data);
    213   else if (&signature == &onc::kOpenVPNSignature)
    214     TranslateOpenVPN(onc_object, ui_data);
    215 
    216   // Recurse into nested objects.
    217   for (base::DictionaryValue::Iterator it(onc_object); !it.IsAtEnd();
    218        it.Advance()) {
    219     const base::DictionaryValue* inner_object;
    220     if (!it.value().GetAsDictionary(&inner_object))
    221       continue;
    222 
    223     const onc::OncFieldSignature* field_signature =
    224         GetFieldSignature(signature, it.key());
    225 
    226     TranslateONCHierarchy(*field_signature->value_signature, *inner_object,
    227                           ui_data);
    228   }
    229 }
    230 
    231 }  // namespace
    232 
    233 // static
    234 scoped_ptr<NetworkUIData> NetworkUIData::CreateFromONC(
    235     ::onc::ONCSource onc_source,
    236     const base::DictionaryValue& onc_network) {
    237   scoped_ptr<NetworkUIData> ui_data(new NetworkUIData());
    238   TranslateONCHierarchy(onc::kNetworkConfigurationSignature, onc_network,
    239                         ui_data.get());
    240 
    241   ui_data->set_onc_source(onc_source);
    242 
    243   return ui_data.Pass();
    244 }
    245 
    246 }  // namespace chromeos
    247