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