shill: provide username/password support for PPP dongles

Add PPP username and password properties to CellularService,
and provide these values to pppd when queried via the GetLogin
callback.

Note that we're not really sure whether or not PPP username/password
is used for network authentication, as the PPP endpoint may
be on the dongle itself.

Nonetheless, provide this functionality in case it proves to
be necessary.

While there: remove some storage constants from the public interface
of Cellular.

BUG=chromium:246443
TEST=unit tests, manual

Manual test
-----------
- restart shill SHILL_LOG_LEVEL=-5 SHILL_LOG_SCOPES=+cellular+service+ppp
- plug in dongle
- wait for cellular to connect
- find cellular service in chrome://network (e.g. "/service/2")
- dbus-send --system --print-reply --dest=org.chromium.flimflam \
    <service> org.chromium.flimflam.Service.SetProperty \
    string:Cellular.PPP.Username variant:string:fake-userid
  in this example, <service> would be /service/2
- grep "Cellular.PPP.Username=fake-userid" /var/run/shill/user_profiles/chronos/shill.profile
  (if not logged in to chromeos, use /var/cache/shill/default.profile instead)
  -> should match
- remove dongle
- insert dongle
- wait for cellular to connect
- egrep "fake-userid" /var/log/net.log
  -> should match. e.g.
  <timestamp> localhost pppd[<pid>]: sent [CHAP Response id=0x1 <random string>, name = "fake-userid"]

Change-Id: I55954e76ab3ab3c911406bf76fbc879fa5e85849
Reviewed-on: https://gerrit.chromium.org/gerrit/59509
Commit-Queue: mukesh agrawal <quiche@chromium.org>
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Tested-by: mukesh agrawal <quiche@chromium.org>
diff --git a/cellular.cc b/cellular.cc
index 5602d14..3f31e30 100644
--- a/cellular.cc
+++ b/cellular.cc
@@ -792,8 +792,14 @@
 // called by |ppp_task_|
 void Cellular::GetLogin(string *user, string *password) {
   LOG(INFO) << __func__;
-  // TODO(quiche): Determine whether or not we need support for PPP
-  // username/password. (crbug.com/246443)
+  if (!service()) {
+    LOG(ERROR) << __func__ << " with no service ";
+    return;
+  }
+  CHECK(user);
+  CHECK(password);
+  *user = service()->ppp_username();
+  *password = service()->ppp_password();
 }
 
 // Called by |ppp_task_|.
diff --git a/cellular_service.cc b/cellular_service.cc
index d5a54c0..ba9c313 100644
--- a/cellular_service.cc
+++ b/cellular_service.cc
@@ -26,14 +26,21 @@
 const int64 CellularService::kOutOfCreditsConnectionDropSeconds = 15;
 const int CellularService::kOutOfCreditsMaxConnectAttempts = 3;
 const int64 CellularService::kOutOfCreditsResumeIgnoreSeconds = 5;
-const char CellularService::kStorageAPN[] = "Cellular.APN";
-const char CellularService::kStorageLastGoodAPN[] = "Cellular.LastGoodAPN";
 
 // TODO(petkov): Add these to system_api/dbus/service_constants.h
 namespace {
 const char kKeyOLPURL[] = "url";
 const char kKeyOLPMethod[] = "method";
 const char kKeyOLPPostData[] = "postdata";
+const char kCellularPPPUsernameProperty[] = "Cellular.PPP.Username";
+const char kCellularPPPPasswordProperty[] = "Cellular.PPP.Password";
+}  // namespace
+
+namespace {
+const char kStorageAPN[] = "Cellular.APN";
+const char kStorageLastGoodAPN[] = "Cellular.LastGoodAPN";
+const char kStoragePPPUsername[] = "Cellular.PPP.Username";
+const char kStoragePPPPassword[] = "Cellular.PPP.Password";
 }  // namespace
 
 static bool GetNonEmptyField(const Stringmap &stringmap,
@@ -124,6 +131,8 @@
   store->RegisterConstStringmap(flimflam::kServingOperatorProperty,
                                 &serving_operator_.ToDict());
   store->RegisterConstString(flimflam::kUsageURLProperty, &usage_url_);
+  store->RegisterString(kCellularPPPUsernameProperty, &ppp_username_);
+  store->RegisterWriteOnlyString(kCellularPPPPasswordProperty, &ppp_password_);
 
   string name = device->CreateFriendlyServiceName();
   set_friendly_name(name);
@@ -239,6 +248,8 @@
   const string id = GetStorageIdentifier();
   LoadApn(storage, id, kStorageAPN, &apn_info_);
   LoadApn(storage, id, kStorageLastGoodAPN, &last_good_apn_info_);
+  storage->GetString(id, kStoragePPPUsername, &ppp_username_);
+  storage->GetString(id, kStoragePPPPassword, &ppp_password_);
   return true;
 }
 
@@ -370,6 +381,8 @@
   const string id = GetStorageIdentifier();
   SaveApn(storage, id, GetUserSpecifiedApn(), kStorageAPN);
   SaveApn(storage, id, GetLastGoodApn(), kStorageLastGoodAPN);
+  SaveString(storage, id, kStoragePPPUsername, ppp_username_, false, true);
+  SaveString(storage, id, kStoragePPPPassword, ppp_password_, false, true);
   return true;
 }
 
diff --git a/cellular_service.h b/cellular_service.h
index 12a7335..05f52fd 100644
--- a/cellular_service.h
+++ b/cellular_service.h
@@ -25,9 +25,6 @@
 
 class CellularService : public Service {
  public:
-  static const char kStorageAPN[];
-  static const char kStorageLastGoodAPN[];
-
   // Online payment portal.
   class OLP {
    public:
@@ -100,6 +97,9 @@
     return is_auto_connecting_;
   }
 
+  const std::string &ppp_username() const { return ppp_username_; }
+  const std::string &ppp_password() const { return ppp_password_; }
+
   void set_enforce_out_of_credits_detection(bool state) {
     enforce_out_of_credits_detection_ = state;
   }
@@ -132,6 +132,7 @@
   FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateServiceName);
   FRIEND_TEST(CellularCapabilityUniversalMainTest, UpdateStorageIdentifier);
   FRIEND_TEST(CellularTest, Connect);
+  FRIEND_TEST(CellularTest, GetLogin);  // ppp_username_, ppp_password_
   FRIEND_TEST(CellularTest, OnConnectionHealthCheckerResult);
   FRIEND_TEST(CellularServiceTest, SetApn);
   FRIEND_TEST(CellularServiceTest, ClearApn);
@@ -201,9 +202,10 @@
   std::string roaming_state_;
   OLP olp_;
   std::string usage_url_;
-
   Stringmap apn_info_;
   Stringmap last_good_apn_info_;
+  std::string ppp_username_;
+  std::string ppp_password_;
 
   std::string storage_identifier_;
 
diff --git a/cellular_unittest.cc b/cellular_unittest.cc
index 7289036..fdf66cb 100644
--- a/cellular_unittest.cc
+++ b/cellular_unittest.cc
@@ -991,6 +991,22 @@
   EXPECT_TRUE(device_->allow_roaming_);
 }
 
+TEST_F(CellularTest, GetLogin) {
+  // Doesn't crash when there is no service.
+  string username_to_pppd;
+  string password_to_pppd;
+  EXPECT_FALSE(device_->service());
+  device_->GetLogin(&username_to_pppd, &password_to_pppd);
+
+  // Provides expected username and password in normal case.
+  const char kFakeUsername[] = "fake-user";
+  const char kFakePassword[] = "fake-password";
+  CellularService &service(*SetService());
+  service.ppp_username_ = kFakeUsername;
+  service.ppp_password_ = kFakePassword;
+  device_->GetLogin(&username_to_pppd, &password_to_pppd);
+}
+
 // Custom property setters should return false, and make no changes, if
 // the new value is the same as the old value.
 TEST_F(CellularTest, CustomSetterNoopChange) {
diff --git a/doc/service-api.txt b/doc/service-api.txt
index 749a66d..907bfa9 100644
--- a/doc/service-api.txt
+++ b/doc/service-api.txt
@@ -326,6 +326,14 @@
 			(Cellular only) Indicates whether a cellular service
 			has any remaining bandwidth credits with the carrier.
 
+		string Cellular.PPP.Username [readwrite]
+			(Cellular only) For cellular devices with a PPP
+			link-layer, the username for PPP authentication.
+
+		string Cellular.PPP.Password [writeonly]
+			(Cellular only) For cellular devices with a PPP
+			link-layer, the password for PPP authentication.
+
 		string CheckPortal [readwrite]
 
 			Control captive portal checking.  Possible values