1 // Copyright 2015 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "webservd/server.h"
16 
17 #include <openssl/evp.h>
18 #include <openssl/x509.h>
19 
20 #include <limits>
21 
22 #include <base/files/file_util.h>
23 #include <base/rand_util.h>
24 #include <base/strings/stringprintf.h>
25 #include <brillo/dbus/async_event_sequencer.h>
26 
27 #include "webservd/dbus_protocol_handler.h"
28 #include "webservd/encryptor.h"
29 #include "webservd/protocol_handler.h"
30 #include "webservd/utils.h"
31 
32 using brillo::dbus_utils::AsyncEventSequencer;
33 using brillo::dbus_utils::DBusObject;
34 using brillo::dbus_utils::ExportedObjectManager;
35 
36 namespace {
37 
38 #ifdef __ANDROID__
39 const char kCertificateFile[] = "/data/misc/webservd/certificate";
40 const char kKeyFile[] = "/data/misc/webservd/key";
41 #else
42 const char kCertificateFile[] = "/var/lib/webservd-certificate";
43 const char kKeyFile[] = "/var/lib/webservd-key";
44 #endif
45 
OnFirewallSuccess(const std::string & itf_name,uint16_t port,bool allowed)46 void OnFirewallSuccess(const std::string& itf_name,
47                        uint16_t port,
48                        bool allowed) {
49   if (allowed) {
50     LOG(INFO) << "Successfully opened up port " << port << " on interface "
51               << itf_name;
52   } else {
53     LOG(ERROR) << "Failed to open up port " << port << ", interface: "
54                << itf_name;
55   }
56 }
57 
IgnoreFirewallDBusMethodError(brillo::Error *)58 void IgnoreFirewallDBusMethodError(brillo::Error* /* error */) {
59 }
60 
LoadAndValidatePrivateKey(const base::FilePath & key_file,webservd::Encryptor * encryptor)61 brillo::SecureBlob LoadAndValidatePrivateKey(const base::FilePath& key_file,
62                                              webservd::Encryptor* encryptor) {
63   std::string encrypted_key_data;
64   if (!base::ReadFileToString(key_file, &encrypted_key_data))
65     return {};
66   std::string key_data;
67   if (!encryptor->DecryptWithAuthentication(encrypted_key_data, &key_data))
68     return {};
69   brillo::SecureBlob key{key_data};
70   if (!webservd::ValidateRSAPrivateKey(key))
71     key.clear();
72   return key;
73 }
74 
75 }  // anonymous namespace
76 
77 namespace webservd {
78 
Server(ExportedObjectManager * object_manager,const Config & config,std::unique_ptr<FirewallInterface> firewall)79 Server::Server(ExportedObjectManager* object_manager, const Config& config,
80                std::unique_ptr<FirewallInterface> firewall)
81     : dbus_object_{new DBusObject{
82           object_manager, object_manager->GetBus(),
83           org::chromium::WebServer::ServerAdaptor::GetObjectPath()}},
84       default_encryptor_{Encryptor::CreateDefaultEncryptor()},
85       encryptor_{default_encryptor_.get()},
86       config_{config},
87       firewall_{std::move(firewall)} {
88   dbus_adaptor_.SetDefaultRequestTimeout(
89       config_.default_request_timeout_seconds);
90 }
91 
~Server()92 Server::~Server() {}
93 
RegisterAsync(const AsyncEventSequencer::CompletionAction & completion_callback)94 void Server::RegisterAsync(
95     const AsyncEventSequencer::CompletionAction& completion_callback) {
96   scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
97   dbus_adaptor_.RegisterWithDBusObject(dbus_object_.get());
98 
99   InitTlsData();
100 
101   for (auto& handler_config : config_.protocol_handlers)
102     CreateProtocolHandler(&handler_config);
103 
104   firewall_->WaitForServiceAsync(dbus_object_->GetBus().get(),
105                                  base::Bind(&Server::OnFirewallServiceOnline,
106                                             weak_ptr_factory_.GetWeakPtr()));
107 
108   dbus_object_->RegisterAsync(
109       sequencer->GetHandler("Failed exporting Server.", true));
110 
111   for (const auto& pair : protocol_handler_map_) {
112     pair.second->RegisterAsync(
113         sequencer->GetHandler("Failed exporting ProtocolHandler.", false));
114   }
115   sequencer->OnAllTasksCompletedCall({completion_callback});
116 }
117 
OnFirewallServiceOnline()118 void Server::OnFirewallServiceOnline() {
119   LOG(INFO) << "Firewall service is on-line. "
120             << "Opening firewall for protocol handlers";
121   for (auto& handler_config : config_.protocol_handlers) {
122     VLOG(1) << "Firewall request: Protocol Handler = " << handler_config.name
123             << ", Port = " << handler_config.port << ", Interface = "
124             << handler_config.interface_name;
125     firewall_->PunchTcpHoleAsync(
126         handler_config.port,
127         handler_config.interface_name,
128         base::Bind(&OnFirewallSuccess, handler_config.interface_name,
129                    handler_config.port),
130         base::Bind(&IgnoreFirewallDBusMethodError));
131   }
132 }
133 
Ping()134 std::string Server::Ping() {
135   return "Web Server is running";
136 }
137 
ProtocolHandlerStarted(ProtocolHandler * handler)138 void Server::ProtocolHandlerStarted(ProtocolHandler* handler) {
139   CHECK(protocol_handler_map_.find(handler) == protocol_handler_map_.end())
140       << "Protocol handler already registered";
141   std::string path = base::StringPrintf("/org/chromium/WebServer/Servers/%d",
142                                         ++last_protocol_handler_index_);
143   dbus::ObjectPath object_path{path};
144   std::unique_ptr<DBusProtocolHandler> dbus_protocol_handler{
145       new DBusProtocolHandler{dbus_object_->GetObjectManager().get(),
146                               object_path,
147                               handler,
148                               this}
149   };
150   protocol_handler_map_.emplace(handler, std::move(dbus_protocol_handler));
151 }
152 
ProtocolHandlerStopped(ProtocolHandler * handler)153 void Server::ProtocolHandlerStopped(ProtocolHandler* handler) {
154   CHECK_EQ(1u, protocol_handler_map_.erase(handler))
155       << "Unknown protocol handler";
156 }
157 
CreateProtocolHandler(Config::ProtocolHandler * handler_config)158 void Server::CreateProtocolHandler(Config::ProtocolHandler* handler_config) {
159   std::unique_ptr<ProtocolHandler> protocol_handler{
160       new ProtocolHandler{handler_config->name, this}};
161   if (protocol_handler->Start(handler_config))
162     protocol_handlers_.push_back(std::move(protocol_handler));
163 }
164 
InitTlsData()165 void Server::InitTlsData() {
166   if (!TLS_certificate_.empty())
167     return;  // Already initialized.
168 
169   // TODO(avakulenko): verify these constants and provide sensible values
170   // for the long-term. See brbug.com/227
171   const int kKeyLengthBits = 1024;
172   const int64_t kOneYearInSeconds = 31556952;  // 365.2425 days
173   const base::TimeDelta kCertExpiration =
174       base::TimeDelta::FromSeconds(5 * kOneYearInSeconds);
175   const char kCommonName[] = "Brillo device";
176 
177   const base::FilePath certificate_file{kCertificateFile};
178   const base::FilePath key_file{kKeyFile};
179 
180   auto cert = LoadAndValidateCertificate(certificate_file);
181   brillo::SecureBlob private_key =
182       LoadAndValidatePrivateKey(key_file, encryptor_);
183   if (!cert || private_key.empty()) {
184     // Create the X509 certificate.
185     LOG(INFO) << "Generating new certificate...";
186     int cert_serial_number = base::RandInt(0, std::numeric_limits<int>::max());
187     cert = CreateCertificate(cert_serial_number, kCertExpiration, kCommonName);
188 
189     // Create RSA key pair.
190     auto rsa_key_pair = GenerateRSAKeyPair(kKeyLengthBits);
191 
192     // Store the private key to a temp buffer.
193     // Do not assign it to |TLS_private_key_| yet until the end when we are sure
194     // everything else has worked out.
195     private_key = StoreRSAPrivateKey(rsa_key_pair.get());
196 
197     // Create EVP key and set it to the certificate.
198     auto key = std::unique_ptr<EVP_PKEY, void (*)(EVP_PKEY*)>{EVP_PKEY_new(),
199                                                               EVP_PKEY_free};
200     CHECK(key.get());
201     // Transfer ownership of |rsa_key_pair| to |key|.
202     CHECK(EVP_PKEY_assign_RSA(key.get(), rsa_key_pair.release()));
203     CHECK(X509_set_pubkey(cert.get(), key.get()));
204 
205     // Sign the certificate.
206     CHECK(X509_sign(cert.get(), key.get(), EVP_sha256()));
207 
208     // Save the certificate and private key to disk.
209     StoreCertificate(cert.get(), certificate_file);
210     std::string encrypted_key;
211     encryptor_->EncryptWithAuthentication(private_key.to_string(),
212                                           &encrypted_key);
213     base::WriteFile(key_file, encrypted_key.data(), encrypted_key.size());
214   }
215 
216   TLS_certificate_ = StoreCertificate(cert.get());
217   TLS_certificate_fingerprint_ = GetSha256Fingerprint(cert.get());
218   TLS_private_key_ = std::move(private_key);
219 
220   // Update the TLS data in protocol handler config.
221   for (auto& handler_config : config_.protocol_handlers) {
222     if (handler_config.use_tls) {
223       handler_config.certificate = TLS_certificate_;
224       handler_config.certificate_fingerprint = TLS_certificate_fingerprint_;
225       handler_config.private_key = TLS_private_key_;
226     }
227   }
228 }
229 
GetUploadDirectory() const230 base::FilePath Server::GetUploadDirectory() const {
231   base::FilePath upload_dir;
232 #ifdef __ANDROID__
233   upload_dir = base::FilePath{"/data/misc/webservd/uploads"};
234 #else
235   CHECK(base::GetTempDir(&upload_dir));
236 #endif
237   return upload_dir;
238 }
239 
240 }  // namespace webservd
241