shill: Make EapPassword and EapPrivateKeyPassword write-only

In the same vein as the Passphrase property in WiFiService,
make these properties unavailable for read-back.

BUG=chromium-os:25690
TEST=New unit test

Change-Id: Ic2e61c0110d593d22c447206a35a0e9982e46aae
Reviewed-on: https://gerrit.chromium.org/gerrit/15078
Commit-Ready: Paul Stewart <pstew@chromium.org>
Reviewed-by: Paul Stewart <pstew@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
diff --git a/service.cc b/service.cc
index 4ac4685..70cb9cc 100644
--- a/service.cc
+++ b/service.cc
@@ -123,13 +123,14 @@
   store_.RegisterString(flimflam::kEAPClientCertProperty, &eap_.client_cert);
   store_.RegisterString(flimflam::kEAPCertIDProperty, &eap_.cert_id);
   store_.RegisterString(flimflam::kEapPrivateKeyProperty, &eap_.private_key);
-  store_.RegisterString(flimflam::kEapPrivateKeyPasswordProperty,
-                        &eap_.private_key_password);
+  HelpRegisterDerivedString(flimflam::kEapPrivateKeyPasswordProperty, NULL,
+                            &Service::SetEAPPrivateKeyPassword);
   store_.RegisterString(flimflam::kEAPKeyIDProperty, &eap_.key_id);
   store_.RegisterString(flimflam::kEapCaCertProperty, &eap_.ca_cert);
   store_.RegisterString(flimflam::kEapCaCertIDProperty, &eap_.ca_cert_id);
   store_.RegisterString(flimflam::kEAPPINProperty, &eap_.pin);
-  store_.RegisterString(flimflam::kEapPasswordProperty, &eap_.password);
+  HelpRegisterDerivedString(flimflam::kEapPasswordProperty, NULL,
+                            &Service::SetEAPPassword);
   store_.RegisterString(flimflam::kEapKeyMgmtProperty, &eap_.key_management);
   store_.RegisterBool(flimflam::kEapUseSystemCAsProperty, &eap_.use_system_cas);
 
@@ -709,6 +710,15 @@
   }
 }
 
+void Service::SetEAPPassword(const string &password, Error */*error*/) {
+  eap_.password = password;
+}
+
+void Service::SetEAPPrivateKeyPassword(const string &password,
+                                       Error */*error*/) {
+  eap_.private_key_password = password;
+}
+
 string Service::GetProfileRpcId(Error *error) {
   if (!profile_) {
     // This happens in some unit tests where profile_ is not set.
diff --git a/service.h b/service.h
index 44efa5d..47f6358 100644
--- a/service.h
+++ b/service.h
@@ -284,6 +284,8 @@
   EventDispatcher *dispatcher() const { return dispatcher_; }
   const std::string &GetEAPKeyManagement() const;
   void SetEAPKeyManagement(const std::string &key_management);
+  void SetEAPPassword(const std::string &password, Error *error);
+  void SetEAPPrivateKeyPassword(const std::string &password, Error *error);
   Metrics *metrics() const { return metrics_; }
 
  private:
diff --git a/service_unittest.cc b/service_unittest.cc
index 8f2daab..24cd06c 100644
--- a/service_unittest.cc
+++ b/service_unittest.cc
@@ -35,6 +35,7 @@
 using testing::StrictMock;
 using testing::SetArgumentPointee;
 using testing::Test;
+using testing::Values;
 
 namespace shill {
 
@@ -330,4 +331,25 @@
   EXPECT_FALSE(service_->IsAutoConnectable());
 }
 
+// Make sure a property is registered as a write only property
+// by reading and comparing all string properties returned on the store.
+// Subtle: We need to convert the test argument back and forth between
+// string and ::DBus::Variant because this is the parameter type that
+// our supeclass (PropertyStoreTest) is declared with.
+class ReadOnlyServicePropertyTest : public ServiceTest {};
+TEST_P(ReadOnlyServicePropertyTest, PropertyWriteOnly) {
+  ReadablePropertyConstIterator<string> it =
+      (service_->store()).GetStringPropertiesIter();
+  string property(GetParam().reader().get_string());
+  for( ; !it.AtEnd(); it.Advance())
+    EXPECT_NE(it.Key(), property);
+}
+
+INSTANTIATE_TEST_CASE_P(
+    ReadOnlyServicePropertyTestInstance,
+    ReadOnlyServicePropertyTest,
+    Values(
+        DBusAdaptor::StringToVariant(flimflam::kEapPrivateKeyPasswordProperty),
+        DBusAdaptor::StringToVariant(flimflam::kEapPasswordProperty)));
+
 }  // namespace shill