1//
2// Copyright (C) 2013 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//      http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17#include "shill/eap_credentials.h"
18
19#include <base/stl_util.h>
20#if defined(__ANDROID__)
21#include <dbus/service_constants.h>
22#else
23#include <chromeos/dbus/service_constants.h>
24#endif  // __ANDROID__
25#include <gtest/gtest.h>
26
27#include "shill/key_value_store.h"
28#include "shill/mock_certificate_file.h"
29#include "shill/mock_event_dispatcher.h"
30#include "shill/mock_log.h"
31#include "shill/mock_metrics.h"
32#include "shill/mock_property_store.h"
33#include "shill/mock_store.h"
34#include "shill/supplicant/wpa_supplicant.h"
35#include "shill/technology.h"
36
37using base::FilePath;
38using std::map;
39using std::string;
40using std::vector;
41using testing::_;
42using testing::AnyNumber;
43using testing::DoAll;
44using testing::HasSubstr;
45using testing::Mock;
46using testing::Return;
47using testing::SetArgumentPointee;
48
49namespace shill {
50
51class EapCredentialsTest : public testing::Test {
52 public:
53  EapCredentialsTest() {}
54  virtual ~EapCredentialsTest() {}
55
56 protected:
57  void PopulateSupplicantProperties() {
58    eap_.PopulateSupplicantProperties(&certificate_file_, &params_);
59  }
60
61  void SetAnonymousIdentity(const string& anonymous_identity) {
62    eap_.anonymous_identity_ = anonymous_identity;
63  }
64  void SetCACertNSS(const string& ca_cert_nss) {
65    eap_.ca_cert_nss_ = ca_cert_nss;
66  }
67  void SetCACertPEM(const vector<string>& ca_cert_pem) {
68    eap_.ca_cert_pem_ = ca_cert_pem;
69  }
70  void SetClientCert(const string& client_cert) {
71    eap_.client_cert_ = client_cert;
72  }
73  void SetCertId(const string& cert_id) {
74    eap_.cert_id_ = cert_id;
75  }
76  void SetCACertId(const string& ca_cert_id) {
77    eap_.ca_cert_id_ = ca_cert_id;
78  }
79  void SetEap(const string& eap) {
80    eap_.eap_ = eap;
81  }
82  void SetIdentity(const string& identity) {
83    eap_.identity_ = identity;
84  }
85  void SetInnerEap(const string& inner_eap) {
86    eap_.inner_eap_ = inner_eap;
87  }
88  void SetKeyId(const string& key_id) {
89    eap_.key_id_ = key_id;
90  }
91  const string& GetPassword() {
92    return eap_.password_;
93  }
94  void SetPassword(const string& password) {
95    eap_.password_ = password;
96  }
97  void SetPrivateKey(const string& private_key) {
98    eap_.private_key_ = private_key;
99  }
100  void SetPin(const string& pin) {
101    eap_.pin_ = pin;
102  }
103  void SetUseProactiveKeyCaching(bool use_proactive_key_caching) {
104    eap_.use_proactive_key_caching_ = use_proactive_key_caching;
105  }
106  void SetUseSystemCAs(bool use_system_cas) {
107    eap_.use_system_cas_ = use_system_cas;
108  }
109  bool IsReset() {
110    return
111        eap_.anonymous_identity_.empty() &&
112        eap_.cert_id_.empty() &&
113        eap_.client_cert_.empty() &&
114        eap_.identity_.empty() &&
115        eap_.key_id_.empty() &&
116        eap_.password_.empty() &&
117        eap_.pin_.empty() &&
118        eap_.private_key_.empty() &&
119        eap_.private_key_password_.empty() &&
120        eap_.ca_cert_.empty() &&
121        eap_.ca_cert_id_.empty() &&
122        eap_.ca_cert_nss_.empty() &&
123        eap_.ca_cert_pem_.empty() &&
124        eap_.eap_.empty() &&
125        eap_.inner_eap_.empty() &&
126        eap_.subject_match_.empty() &&
127        eap_.use_system_cas_ == true &&
128        eap_.use_proactive_key_caching_ == false;
129  }
130
131  const string& GetKeyManagement() {
132    return eap_.key_management_;
133  }
134  bool SetEapPassword(const string& password, Error* error) {
135    return eap_.SetEapPassword(password, error);
136  }
137  bool SetEapPrivateKeyPassword(const string& password, Error* error) {
138    return eap_.SetEapPrivateKeyPassword(password, error);
139  }
140
141  EapCredentials eap_;
142  MockCertificateFile certificate_file_;
143  KeyValueStore params_;
144};
145
146TEST_F(EapCredentialsTest, PropertyStore) {
147  PropertyStore store;
148  eap_.InitPropertyStore(&store);
149  const string kIdentity("Cross-Eyed Mary");
150  Error error;
151  EXPECT_TRUE(store.SetStringProperty(kEapIdentityProperty, kIdentity, &error));
152  EXPECT_EQ(kIdentity, eap_.identity());
153}
154
155TEST_F(EapCredentialsTest, Connectable) {
156  // Empty EAP credentials should not make a 802.1x network connectable.
157  EXPECT_FALSE(eap_.IsConnectable());
158
159  // Identity alone is not enough.
160  SetIdentity("Steel Monkey");
161  EXPECT_FALSE(eap_.IsConnectable());
162
163  // Set a password.
164  SetPassword("Angry Tapir");
165
166  // Empty "EAP" parameter is treated like "not EAP-TLS", and connectable.
167  EXPECT_TRUE(eap_.IsConnectable());
168
169  // Some other non-TLS EAP type.
170  SetEap("DodgeBall");
171  EXPECT_TRUE(eap_.IsConnectable());
172
173  // EAP-TLS requires certificate parameters, and cares not for passwords.
174  SetEap("TLS");
175  EXPECT_FALSE(eap_.IsConnectable());
176
177  // Clearing the password won't help.
178  SetPassword("");
179  EXPECT_FALSE(eap_.IsConnectable());
180
181  // A client cert by itself doesn't help.
182  SetClientCert("client-cert");
183  EXPECT_FALSE(eap_.IsConnectable());
184
185  // A client cert and key will, however.
186  SetPrivateKey("client-cert");
187  EXPECT_TRUE(eap_.IsConnectable());
188
189  // A key-id (and cert) doesn't work.
190  SetKeyId("client-key-id");
191  EXPECT_FALSE(eap_.IsConnectable());
192
193  // We need a PIN for the key id in addition.
194  SetPin("pin");
195  EXPECT_TRUE(eap_.IsConnectable());
196
197  // If we clear the "EAP" property, we just assume these valid certificate
198  // credentials are the ones to be used.
199  SetEap("");
200  EXPECT_TRUE(eap_.IsConnectable());
201
202  // Check that clearing the certificate parameter breaks us again.
203  SetClientCert("");
204  EXPECT_FALSE(eap_.IsConnectable());
205
206  // Setting the cert-id will fix things.
207  SetCertId("client-cert-id");
208  EXPECT_TRUE(eap_.IsConnectable());
209}
210
211TEST_F(EapCredentialsTest, ConnectableUsingPassphrase) {
212  EXPECT_FALSE(eap_.IsConnectableUsingPassphrase());
213
214  // No password.
215  SetIdentity("TestIdentity");
216  EXPECT_FALSE(eap_.IsConnectableUsingPassphrase());
217
218  // Success.
219  SetPassword("TestPassword");
220  EXPECT_TRUE(eap_.IsConnectableUsingPassphrase());
221
222  // Clear identity.
223  SetIdentity("");
224  EXPECT_FALSE(eap_.IsConnectableUsingPassphrase());
225}
226
227TEST_F(EapCredentialsTest, IsEapAuthenticationProperty) {
228  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
229      kEapAnonymousIdentityProperty));
230  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(kEapCertIdProperty));
231  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
232      kEapClientCertProperty));
233  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
234      kEapIdentityProperty));
235  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(kEapKeyIdProperty));
236  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(kEapKeyMgmtProperty));
237  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
238      kEapPasswordProperty));
239  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(kEapPinProperty));
240  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
241      kEapPrivateKeyProperty));
242  EXPECT_TRUE(EapCredentials::IsEapAuthenticationProperty(
243      kEapPrivateKeyPasswordProperty));
244
245  // It's easier to test that this function returns TRUE in every situation
246  // that it should, than to test all the cases it should return FALSE in.
247  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(kEapCaCertProperty));
248  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
249      kEapCaCertIdProperty));
250  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
251      kEapCaCertNssProperty));
252  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
253      kEapCaCertPemProperty));
254  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(kEapMethodProperty));
255  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
256      kEapPhase2AuthProperty));
257  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
258      kEapRemoteCertificationProperty));
259  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
260      kEapSubjectMatchProperty));
261  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
262      kEapUseProactiveKeyCachingProperty));
263  EXPECT_FALSE(EapCredentials::IsEapAuthenticationProperty(
264      kEapUseSystemCasProperty));
265}
266
267TEST_F(EapCredentialsTest, LoadAndSave) {
268  MockStore store;
269  // For the values we're not testing...
270  EXPECT_CALL(store, GetCryptedString(_, _, _)).WillRepeatedly(Return(false));
271  EXPECT_CALL(store, GetString(_, _, _)).WillRepeatedly(Return(false));
272
273  const string kId("storage-id");
274  const string kIdentity("Purple Onion");
275  EXPECT_CALL(store, GetCryptedString(
276      kId, EapCredentials::kStorageEapIdentity, _))
277      .WillOnce(DoAll(SetArgumentPointee<2>(kIdentity), Return(true)));
278  const string kManagement("Shave and a Haircut");
279  EXPECT_CALL(store, GetString(
280      kId, EapCredentials::kStorageEapKeyManagement, _))
281      .WillOnce(DoAll(SetArgumentPointee<2>(kManagement), Return(true)));
282  const string kPassword("Two Bits");
283  EXPECT_CALL(store, GetCryptedString(
284      kId, EapCredentials::kStorageEapPassword, _))
285      .WillOnce(DoAll(SetArgumentPointee<2>(kPassword), Return(true)));
286
287  eap_.Load(&store, kId);
288  Mock::VerifyAndClearExpectations(&store);
289
290  EXPECT_EQ(kIdentity, eap_.identity());
291  EXPECT_EQ(kManagement, eap_.key_management());
292  EXPECT_EQ(kPassword, GetPassword());
293
294  // Authentication properties are deleted from the store if they are empty,
295  // so we expect the fields that we haven't set to be deleted.
296  EXPECT_CALL(store, DeleteKey(_, _)).Times(AnyNumber());
297  EXPECT_CALL(store, SetCryptedString(_, _, _)).Times(0);
298  EXPECT_CALL(store, DeleteKey(kId, EapCredentials::kStorageEapIdentity));
299  EXPECT_CALL(store, SetString(
300      kId, EapCredentials::kStorageEapKeyManagement, kManagement));
301  EXPECT_CALL(store, DeleteKey(kId, EapCredentials::kStorageEapPassword));
302  eap_.Save(&store, kId, false);
303  Mock::VerifyAndClearExpectations(&store);
304
305  // Authentication properties are deleted from the store if they are empty,
306  // so we expect the fields that we haven't set to be deleted.
307  EXPECT_CALL(store, DeleteKey(_, _)).Times(AnyNumber());
308  EXPECT_CALL(store, SetCryptedString(
309      kId, EapCredentials::kStorageEapIdentity, kIdentity));
310  EXPECT_CALL(store, SetString(
311      kId, EapCredentials::kStorageEapKeyManagement, kManagement));
312  EXPECT_CALL(store, SetCryptedString(
313      kId, EapCredentials::kStorageEapPassword, kPassword));
314  eap_.Save(&store, kId, true);
315}
316
317TEST_F(EapCredentialsTest, OutputConnectionMetrics) {
318  Error unused_error;
319  SetEap(kEapMethodPEAP);
320  SetInnerEap(kEapPhase2AuthPEAPMSCHAPV2);
321
322  MockEventDispatcher dispatcher;
323  MockMetrics metrics(&dispatcher);
324  EXPECT_CALL(metrics, SendEnumToUMA("Network.Shill.Wifi.EapOuterProtocol",
325                                     Metrics::kEapOuterProtocolPeap,
326                                     Metrics::kEapOuterProtocolMax));
327  EXPECT_CALL(metrics, SendEnumToUMA("Network.Shill.Wifi.EapInnerProtocol",
328                                     Metrics::kEapInnerProtocolPeapMschapv2,
329                                     Metrics::kEapInnerProtocolMax));
330  eap_.OutputConnectionMetrics(&metrics, Technology::kWifi);
331}
332
333TEST_F(EapCredentialsTest, PopulateSupplicantProperties) {
334  SetIdentity("testidentity");
335  SetPin("xxxx");
336  PopulateSupplicantProperties();
337  // Test that only non-empty 802.1x properties are populated.
338  EXPECT_TRUE(
339      params_.ContainsString(WPASupplicant::kNetworkPropertyEapIdentity));
340  EXPECT_FALSE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapKeyId));
341  EXPECT_FALSE(
342      params_.ContainsString(WPASupplicant::kNetworkPropertyEapCaCert));
343
344  // Test that CA path is set by default.
345  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyCaPath));
346
347  // Test that hardware-backed security arguments are not set, since
348  // neither key-id nor cert-id were set.
349  EXPECT_FALSE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapPin));
350  EXPECT_FALSE(params_.ContainsUint(WPASupplicant::kNetworkPropertyEngine));
351  EXPECT_FALSE(params_.ContainsString(WPASupplicant::kNetworkPropertyEngineId));
352}
353
354TEST_F(EapCredentialsTest, PopulateSupplicantPropertiesNoSystemCAs) {
355  SetIdentity("testidentity");
356  SetUseSystemCAs(false);
357  PopulateSupplicantProperties();
358  // Test that CA path is not set if use_system_cas is explicitly false.
359  EXPECT_FALSE(params_.ContainsString(WPASupplicant::kNetworkPropertyCaPath));
360}
361
362TEST_F(EapCredentialsTest,
363       PopulateSupplicantPropertiesProactiveKeyCachingDisabledByDefault) {
364  SetIdentity("testidentity");
365  PopulateSupplicantProperties();
366
367  ASSERT_TRUE(params_.ContainsUint(
368      WPASupplicant::kNetworkPropertyEapProactiveKeyCaching));
369
370  const uint32_t kProactiveKeyCachingDisabled(0);
371
372  EXPECT_EQ(kProactiveKeyCachingDisabled,
373            params_.GetUint(
374                WPASupplicant::kNetworkPropertyEapProactiveKeyCaching));
375}
376
377TEST_F(EapCredentialsTest,
378       PopulateSupplicantPropertiesEnableProactiveKeyCaching) {
379  SetIdentity("testidentity");
380  SetUseProactiveKeyCaching(true);
381  PopulateSupplicantProperties();
382
383  ASSERT_TRUE(params_.ContainsUint(
384      WPASupplicant::kNetworkPropertyEapProactiveKeyCaching));
385
386  const uint32_t kProactiveKeyCachingEnabled(1);
387
388  EXPECT_EQ(kProactiveKeyCachingEnabled,
389            params_.GetUint(
390                WPASupplicant::kNetworkPropertyEapProactiveKeyCaching));
391}
392
393TEST_F(EapCredentialsTest,
394       PopulateSupplicantPropertiesDisableProactiveKeyCaching) {
395  SetIdentity("testidentity");
396  SetUseProactiveKeyCaching(false);
397  PopulateSupplicantProperties();
398
399  ASSERT_TRUE(params_.ContainsUint(
400      WPASupplicant::kNetworkPropertyEapProactiveKeyCaching));
401
402  const uint32_t kProactiveKeyCachingDisabled(0);
403
404  EXPECT_EQ(kProactiveKeyCachingDisabled,
405            params_.GetUint(
406                WPASupplicant::kNetworkPropertyEapProactiveKeyCaching));
407}
408
409TEST_F(EapCredentialsTest, PopulateSupplicantPropertiesUsingHardwareAuth) {
410  SetIdentity("testidentity");
411  SetKeyId("key_id");
412  SetPin("xxxx");
413  SetEap("PEAP");
414  PopulateSupplicantProperties();
415  // Test that EAP engine parameters are not set if the authentication type
416  // is not one that accepts a client certificate.
417  EXPECT_FALSE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapPin));
418  EXPECT_FALSE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapKeyId));
419  EXPECT_FALSE(params_.ContainsUint(WPASupplicant::kNetworkPropertyEngine));
420  EXPECT_FALSE(params_.ContainsString(WPASupplicant::kNetworkPropertyEngineId));
421
422  // Test that EAP engine parameters are set if key_id is set and the
423  // authentication type accepts a client certificate.
424  params_.Clear();
425  SetEap("TLS");
426  PopulateSupplicantProperties();
427  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapPin));
428  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapKeyId));
429  EXPECT_TRUE(params_.ContainsUint(WPASupplicant::kNetworkPropertyEngine));
430  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEngineId));
431
432  // An empty EAP parameter should be considered to be possibly "TLS".
433  params_.Clear();
434  SetEap("");
435  PopulateSupplicantProperties();
436  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapPin));
437  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapKeyId));
438  EXPECT_TRUE(params_.ContainsUint(WPASupplicant::kNetworkPropertyEngine));
439  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEngineId));
440
441  // Test that EAP engine parameters are set if ca_cert_id is set even if the
442  // authentication type does not accept a client certificate.  However,
443  // the client key id should not be provided.
444  params_.Clear();
445  SetEap("PEAP");
446  SetCACertId("certid");
447  PopulateSupplicantProperties();
448  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapPin));
449  EXPECT_FALSE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapKeyId));
450  EXPECT_TRUE(params_.ContainsUint(WPASupplicant::kNetworkPropertyEngine));
451  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEngineId));
452  EXPECT_TRUE(
453      params_.ContainsString(WPASupplicant::kNetworkPropertyEapCaCertId));
454}
455
456TEST_F(EapCredentialsTest, PopulateSupplicantPropertiesPEM) {
457  const vector<string> kPemCert{ "-pem-certificate-here-" };
458  SetCACertPEM(kPemCert);
459  const string kPEMCertfile("/tmp/pem-cert");
460  FilePath pem_cert(kPEMCertfile);
461  EXPECT_CALL(certificate_file_, CreatePEMFromStrings(kPemCert))
462      .WillOnce(Return(pem_cert));
463
464  PopulateSupplicantProperties();
465  EXPECT_TRUE(params_.ContainsString(WPASupplicant::kNetworkPropertyEapCaCert));
466  if (params_.ContainsString(WPASupplicant::kNetworkPropertyEapCaCert)) {
467    EXPECT_EQ(kPEMCertfile,
468              params_.GetString(WPASupplicant::kNetworkPropertyEapCaCert));
469  }
470}
471
472TEST_F(EapCredentialsTest, PopulateWiMaxProperties) {
473  {
474    KeyValueStore parameters;
475    eap_.PopulateWiMaxProperties(&parameters);
476
477    EXPECT_FALSE(parameters.ContainsString(
478        wimax_manager::kEAPAnonymousIdentity));
479    EXPECT_FALSE(parameters.ContainsString(
480        wimax_manager::kEAPUserIdentity));
481    EXPECT_FALSE(parameters.ContainsString(
482        wimax_manager::kEAPUserPassword));
483  }
484
485  const string kAnonymousIdentity("TestAnonymousIdentity");
486  SetAnonymousIdentity(kAnonymousIdentity);
487  const string kIdentity("TestUserIdentity");
488  SetIdentity(kIdentity);
489  const string kPassword("TestPassword");
490  SetPassword(kPassword);
491
492  {
493    KeyValueStore parameters;
494    eap_.PopulateWiMaxProperties(&parameters);
495    EXPECT_EQ(kAnonymousIdentity, parameters.LookupString(
496        wimax_manager::kEAPAnonymousIdentity, ""));
497    EXPECT_EQ(kIdentity, parameters.LookupString(
498        wimax_manager::kEAPUserIdentity, ""));
499    EXPECT_EQ(kPassword, parameters.LookupString(
500        wimax_manager::kEAPUserPassword, ""));
501  }
502}
503
504TEST_F(EapCredentialsTest, Reset) {
505  EXPECT_TRUE(IsReset());
506  EXPECT_TRUE(GetKeyManagement().empty());
507  SetAnonymousIdentity("foo");
508  SetCACertId("foo");
509  SetCACertNSS("foo");
510  SetCACertPEM(vector<string>{ "foo" });
511  SetClientCert("foo");
512  SetCertId("foo");
513  SetEap("foo");
514  SetIdentity("foo");
515  SetInnerEap("foo");
516  SetKeyId("foo");
517  SetPassword("foo");
518  SetPrivateKey("foo");
519  SetPin("foo");
520  SetUseSystemCAs(false);
521  SetUseProactiveKeyCaching(true);
522  eap_.SetKeyManagement("foo", nullptr);
523  EXPECT_FALSE(IsReset());
524  EXPECT_FALSE(GetKeyManagement().empty());
525  eap_.Reset();
526  EXPECT_TRUE(IsReset());
527  EXPECT_FALSE(GetKeyManagement().empty());
528}
529
530TEST_F(EapCredentialsTest, SetKeyManagement) {
531  const string kKeyManagement0("foo");
532  eap_.SetKeyManagement(kKeyManagement0, nullptr);
533  EXPECT_EQ(kKeyManagement0, GetKeyManagement());
534
535  const string kKeyManagement1("bar");
536  eap_.SetKeyManagement(kKeyManagement1, nullptr);
537  EXPECT_EQ(kKeyManagement1, GetKeyManagement());
538
539  // We should not be able to set the key management to an empty string.
540  eap_.SetKeyManagement("", nullptr);
541  EXPECT_EQ(kKeyManagement1, GetKeyManagement());
542}
543
544// Custom property setters should return false, and make no changes, if
545// the new value is the same as the old value.
546TEST_F(EapCredentialsTest, CustomSetterNoopChange) {
547  // SetEapKeyManagement
548  {
549    const string kKeyManagement("foo");
550    Error error;
551    // Set to known value.
552    EXPECT_TRUE(eap_.SetKeyManagement(kKeyManagement, &error));
553    EXPECT_TRUE(error.IsSuccess());
554    // Set to same value.
555    EXPECT_FALSE(eap_.SetKeyManagement(kKeyManagement, &error));
556    EXPECT_TRUE(error.IsSuccess());
557  }
558
559  // SetEapPassword
560  {
561    const string kPassword("foo");
562    Error error;
563    // Set to known value.
564    EXPECT_TRUE(SetEapPassword(kPassword, &error));
565    EXPECT_TRUE(error.IsSuccess());
566    // Set to same value.
567    EXPECT_FALSE(SetEapPassword(kPassword, &error));
568    EXPECT_TRUE(error.IsSuccess());
569  }
570
571  // SetEapPrivateKeyPassword
572  {
573    const string kPrivateKeyPassword("foo");
574    Error error;
575    // Set to known value.
576    EXPECT_TRUE(SetEapPrivateKeyPassword(kPrivateKeyPassword, &error));
577    EXPECT_TRUE(error.IsSuccess());
578    // Set to same value.
579    EXPECT_FALSE(SetEapPrivateKeyPassword(kPrivateKeyPassword, &error));
580    EXPECT_TRUE(error.IsSuccess());
581  }
582}
583
584}  // namespace shill
585