Merge lp:~phablet-team/media-hub/introduce-apparmor-interfaces into lp:media-hub
- introduce-apparmor-interfaces
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Ricardo Mendoza |
Approved revision: | 122 |
Merged at revision: | 123 |
Proposed branch: | lp:~phablet-team/media-hub/introduce-apparmor-interfaces |
Merge into: | lp:media-hub |
Prerequisite: | lp:~phablet-team/media-hub/introduce-call-monitor-interface |
Diff against target: |
1302 lines (+685/-313) 15 files modified
src/core/media/CMakeLists.txt (+3/-0) src/core/media/apparmor.h (+0/-93) src/core/media/apparmor/context.cpp (+34/-0) src/core/media/apparmor/context.h (+51/-0) src/core/media/apparmor/dbus.h (+94/-0) src/core/media/apparmor/ubuntu.cpp (+198/-0) src/core/media/apparmor/ubuntu.h (+167/-0) src/core/media/player.cpp (+0/-1) src/core/media/player_configuration.h (+0/-3) src/core/media/player_implementation.cpp (+2/-1) src/core/media/player_implementation.h (+3/-1) src/core/media/player_skeleton.cpp (+16/-93) src/core/media/player_skeleton.h (+9/-3) src/core/media/service_implementation.cpp (+9/-2) src/core/media/service_skeleton.cpp (+99/-116) |
To merge this branch: | bzr merge lp:~phablet-team/media-hub/introduce-apparmor-interfaces |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Jim Hodapp | code | Pending | |
Review via email: mp+251807@code.launchpad.net |
This proposal supersedes a proposal from 2015-03-04.
Commit message
Add an interface apparmor:
Add an interface apparmor:
Provide an implementation apparmor:
Provide an implementation apparmor:
Remove obsolete query for the apparmor profile in ServiceSkeleton.
Adjust the implementation in media::
Description of the change
Add an interface apparmor:
Add an interface apparmor:
Provide an implementation apparmor:
Provide an implementation apparmor:
Remove obsolete query for the apparmor profile in ServiceSkeleton.
Adjust the implementation in media::
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
Jim Hodapp (jhodapp) wrote : Posted in a previous version of this proposal | # |
One simple comment below.
Thomas Voß (thomas-voss) : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:115
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:116
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:117
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PASSED: Continuous integration, rev:118
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:119
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 121. By Ricardo Salveti
-
Merge prereq
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:120
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:121
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 122. By Thomas Voß
-
* debian/control:
- Removing pre-depends that are not required
- Bumping standards-version to 3.9.6
[ Ricardo Salveti de Araujo ]
* Migrating tests to use ogg instead of mp3/avi removed:
tests/h264.avi tests/test.mp3 added: tests/test-audio-1. ogg
tests/test-video. ogg tests/test.mp3 renamed: tests/test.ogg =>
tests/test-audio. ogg
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:122
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'src/core/media/CMakeLists.txt' |
2 | --- src/core/media/CMakeLists.txt 2015-03-12 11:45:23 +0000 |
3 | +++ src/core/media/CMakeLists.txt 2015-03-12 11:45:23 +0000 |
4 | @@ -91,6 +91,9 @@ |
5 | cover_art_resolver.cpp |
6 | engine.cpp |
7 | |
8 | + apparmor/context.cpp |
9 | + apparmor/ubuntu.cpp |
10 | + |
11 | audio/pulse_audio_output_observer.cpp |
12 | audio/ostream_reporter.cpp |
13 | audio/output_observer.cpp |
14 | |
15 | === added directory 'src/core/media/apparmor' |
16 | === removed file 'src/core/media/apparmor.h' |
17 | --- src/core/media/apparmor.h 2014-09-01 07:49:45 +0000 |
18 | +++ src/core/media/apparmor.h 1970-01-01 00:00:00 +0000 |
19 | @@ -1,93 +0,0 @@ |
20 | -/* |
21 | - * Copyright (C) 2013-2014 Canonical Ltd |
22 | - * |
23 | - * This program is free software: you can redistribute it and/or modify |
24 | - * it under the terms of the GNU Lesser General Public License version 3 as |
25 | - * published by the Free Software Foundation. |
26 | - * |
27 | - * This program is distributed in the hope that it will be useful, |
28 | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
29 | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
30 | - * GNU Lesser General Public License for more details. |
31 | - * |
32 | - * You should have received a copy of the GNU Lesser General Public License |
33 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
34 | - * |
35 | - * Author: Jim Hodapp <jim.hodapp@canonical.com> |
36 | - */ |
37 | - |
38 | -#ifndef APPARMOR_DBUS_H_ |
39 | -#define APPARMOR_DBUS_H_ |
40 | - |
41 | -#include <core/dbus/macros.h> |
42 | -#include <core/dbus/object.h> |
43 | -#include <core/dbus/service.h> |
44 | - |
45 | -#include <string> |
46 | -#include <chrono> |
47 | - |
48 | -// TODO(tvoss): This really should live in trust-store, providing a straightforward |
49 | -// way for parties involved in managing trust relationships to query peers' apparmor |
50 | -// profiles. Please see https://bugs.launchpad.net/trust-store/+bug/1350736 for the |
51 | -// related bug |
52 | -namespace org |
53 | -{ |
54 | -namespace freedesktop |
55 | -{ |
56 | -namespace dbus |
57 | -{ |
58 | -struct DBus |
59 | -{ |
60 | - static const std::string& name() |
61 | - { |
62 | - static const std::string s = "org.freedesktop.DBus"; |
63 | - return s; |
64 | - } |
65 | - |
66 | - // Gets the AppArmor confinement string associated with the unique connection name. If |
67 | - // D-Bus is not performing AppArmor mediation, the |
68 | - // org.freedesktop.DBus.Error.AppArmorSecurityContextUnknown error is returned. |
69 | - DBUS_CPP_METHOD_DEF(GetConnectionAppArmorSecurityContext, DBus) |
70 | - |
71 | - struct Stub |
72 | - { |
73 | - // Creates a new stub instance for the given object to access |
74 | - // DBus functionality. |
75 | - Stub(const core::dbus::Object::Ptr& object) : object{object} |
76 | - { |
77 | - } |
78 | - |
79 | - // Creates a new stub instance for the given bus connection |
80 | - Stub(const core::dbus::Bus::Ptr& bus) |
81 | - : object |
82 | - { |
83 | - core::dbus::Service::use_service<org::freedesktop::dbus::DBus>(bus) |
84 | - ->object_for_path(core::dbus::types::ObjectPath{"/org/freedesktop/DBus"}) |
85 | - } |
86 | - { |
87 | - } |
88 | - |
89 | - // Gets the AppArmor confinement string associated with the unique connection name. If |
90 | - // D-Bus is not performing AppArmor mediation, the |
91 | - // org.freedesktop.DBus.Error.AppArmorSecurityContextUnknown error is returned. |
92 | - // |
93 | - // Invokes the given handler on completion. |
94 | - void get_connection_app_armor_security_async( |
95 | - const std::string& name, |
96 | - std::function<void(const std::string&)> handler) |
97 | - { |
98 | - object->invoke_method_asynchronously_with_callback<GetConnectionAppArmorSecurityContext, std::string>( |
99 | - [handler](const core::dbus::Result<std::string>& result) |
100 | - { |
101 | - if (not result.is_error()) handler(result.value()); |
102 | - }, name); |
103 | - } |
104 | - |
105 | - core::dbus::Object::Ptr object; |
106 | - }; |
107 | -}; |
108 | -} |
109 | -} |
110 | -} |
111 | - |
112 | -#endif // APPARMOR_DBUS_H_ |
113 | |
114 | === added file 'src/core/media/apparmor/context.cpp' |
115 | --- src/core/media/apparmor/context.cpp 1970-01-01 00:00:00 +0000 |
116 | +++ src/core/media/apparmor/context.cpp 2015-03-12 11:45:23 +0000 |
117 | @@ -0,0 +1,34 @@ |
118 | +/* |
119 | + * Copyright © 2014 Canonical Ltd. |
120 | + * |
121 | + * This program is free software: you can redistribute it and/or modify it |
122 | + * under the terms of the GNU Lesser General Public License version 3, |
123 | + * as published by the Free Software Foundation. |
124 | + * |
125 | + * This program is distributed in the hope that it will be useful, |
126 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
127 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
128 | + * GNU Lesser General Public License for more details. |
129 | + * |
130 | + * You should have received a copy of the GNU Lesser General Public License |
131 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
132 | + * |
133 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
134 | + */ |
135 | + |
136 | +#include <core/media/apparmor/context.h> |
137 | + |
138 | +namespace apparmor = core::ubuntu::media::apparmor; |
139 | + |
140 | +apparmor::Context::Context(const std::string& name) : name{name} |
141 | +{ |
142 | + if (name.empty()) throw std::runtime_error |
143 | + { |
144 | + "apparmor::Context cannot be created for empty name." |
145 | + }; |
146 | +} |
147 | + |
148 | +const std::string& apparmor::Context::str() const |
149 | +{ |
150 | + return name; |
151 | +} |
152 | |
153 | === added file 'src/core/media/apparmor/context.h' |
154 | --- src/core/media/apparmor/context.h 1970-01-01 00:00:00 +0000 |
155 | +++ src/core/media/apparmor/context.h 2015-03-12 11:45:23 +0000 |
156 | @@ -0,0 +1,51 @@ |
157 | +/* |
158 | + * Copyright © 2014 Canonical Ltd. |
159 | + * |
160 | + * This program is free software: you can redistribute it and/or modify it |
161 | + * under the terms of the GNU Lesser General Public License version 3, |
162 | + * as published by the Free Software Foundation. |
163 | + * |
164 | + * This program is distributed in the hope that it will be useful, |
165 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
166 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
167 | + * GNU Lesser General Public License for more details. |
168 | + * |
169 | + * You should have received a copy of the GNU Lesser General Public License |
170 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
171 | + * |
172 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
173 | + */ |
174 | +#ifndef CORE_UBUNTU_MEDIA_APPARMOR_AUTHENTICATOR_H_ |
175 | +#define CORE_UBUNTU_MEDIA_APPARMOR_AUTHENTICATOR_H_ |
176 | + |
177 | +#include <memory> |
178 | +#include <string> |
179 | + |
180 | +namespace core |
181 | +{ |
182 | +namespace ubuntu |
183 | +{ |
184 | +namespace media |
185 | +{ |
186 | +namespace apparmor |
187 | +{ |
188 | +// Models an apparmor context name, and provides convenience functionality |
189 | +// on top of it. |
190 | +class Context |
191 | +{ |
192 | +public: |
193 | + // Constructs a new Context instance for the given raw name. |
194 | + // Throws std::logic_error for empty names. |
195 | + explicit Context(const std::string& name); |
196 | + virtual ~Context() = default; |
197 | + // Returns the raw string describing the context. |
198 | + const std::string& str() const; |
199 | + |
200 | +private: |
201 | + const std::string name; |
202 | +}; |
203 | +} |
204 | +} |
205 | +} |
206 | +} |
207 | +#endif // CORE_UBUNTU_MEDIA_APPARMOR_AUTHENTICATOR_H_ |
208 | |
209 | === added file 'src/core/media/apparmor/dbus.h' |
210 | --- src/core/media/apparmor/dbus.h 1970-01-01 00:00:00 +0000 |
211 | +++ src/core/media/apparmor/dbus.h 2015-03-12 11:45:23 +0000 |
212 | @@ -0,0 +1,94 @@ |
213 | +/* |
214 | + * Copyright (C) 2013-2014 Canonical Ltd |
215 | + * |
216 | + * This program is free software: you can redistribute it and/or modify |
217 | + * it under the terms of the GNU Lesser General Public License version 3 as |
218 | + * published by the Free Software Foundation. |
219 | + * |
220 | + * This program is distributed in the hope that it will be useful, |
221 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
222 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
223 | + * GNU Lesser General Public License for more details. |
224 | + * |
225 | + * You should have received a copy of the GNU Lesser General Public License |
226 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
227 | + * |
228 | + * Author: Jim Hodapp <jim.hodapp@canonical.com> |
229 | + */ |
230 | + |
231 | +#ifndef CORE_UBUNTU_MEDIA_APPARMOR_DBUS_H_ |
232 | +#define CORE_UBUNTU_MEDIA_APPARMOR_DBUS_H_ |
233 | + |
234 | +#include <core/dbus/bus.h> |
235 | +#include <core/dbus/macros.h> |
236 | +#include <core/dbus/object.h> |
237 | +#include <core/dbus/service.h> |
238 | + |
239 | +#include <string> |
240 | +#include <chrono> |
241 | + |
242 | +// TODO(tvoss): This really should live in trust-store, providing a straightforward |
243 | +// way for parties involved in managing trust relationships to query peers' apparmor |
244 | +// profiles. Please see https://bugs.launchpad.net/trust-store/+bug/1350736 for the |
245 | +// related bug |
246 | +namespace org |
247 | +{ |
248 | +namespace freedesktop |
249 | +{ |
250 | +namespace dbus |
251 | +{ |
252 | +struct DBus |
253 | +{ |
254 | + static const std::string& name() |
255 | + { |
256 | + static const std::string s = "org.freedesktop.DBus"; |
257 | + return s; |
258 | + } |
259 | + |
260 | + // Gets the AppArmor confinement string associated with the unique connection name. If |
261 | + // D-Bus is not performing AppArmor mediation, the |
262 | + // org.freedesktop.DBus.Error.AppArmorSecurityContextUnknown error is returned. |
263 | + DBUS_CPP_METHOD_DEF(GetConnectionAppArmorSecurityContext, DBus) |
264 | + |
265 | + struct Stub |
266 | + { |
267 | + // Creates a new stub instance for the given object to access |
268 | + // DBus functionality. |
269 | + Stub(const core::dbus::Object::Ptr& object) : object{object} |
270 | + { |
271 | + } |
272 | + |
273 | + // Creates a new stub instance for the given bus connection |
274 | + Stub(const core::dbus::Bus::Ptr& bus) |
275 | + : object |
276 | + { |
277 | + core::dbus::Service::use_service<org::freedesktop::dbus::DBus>(bus) |
278 | + ->object_for_path(core::dbus::types::ObjectPath{"/org/freedesktop/DBus"}) |
279 | + } |
280 | + { |
281 | + } |
282 | + |
283 | + // Gets the AppArmor confinement string associated with the unique connection name. If |
284 | + // D-Bus is not performing AppArmor mediation, the |
285 | + // org.freedesktop.DBus.Error.AppArmorSecurityContextUnknown error is returned. |
286 | + // |
287 | + // Invokes the given handler on completion. |
288 | + void get_connection_app_armor_security_async( |
289 | + const std::string& name, |
290 | + std::function<void(const std::string&)> handler) |
291 | + { |
292 | + object->invoke_method_asynchronously_with_callback<GetConnectionAppArmorSecurityContext, std::string>( |
293 | + [handler](const core::dbus::Result<std::string>& result) |
294 | + { |
295 | + if (not result.is_error()) handler(result.value()); |
296 | + }, name); |
297 | + } |
298 | + |
299 | + core::dbus::Object::Ptr object; |
300 | + }; |
301 | +}; |
302 | +} |
303 | +} |
304 | +} |
305 | + |
306 | +#endif // CORE_UBUNTU_MEDIA_APPARMOR_DBUS_H_ |
307 | |
308 | === added file 'src/core/media/apparmor/ubuntu.cpp' |
309 | --- src/core/media/apparmor/ubuntu.cpp 1970-01-01 00:00:00 +0000 |
310 | +++ src/core/media/apparmor/ubuntu.cpp 2015-03-12 11:45:23 +0000 |
311 | @@ -0,0 +1,198 @@ |
312 | +/* |
313 | + * Copyright © 2014 Canonical Ltd. |
314 | + * |
315 | + * This program is free software: you can redistribute it and/or modify it |
316 | + * under the terms of the GNU Lesser General Public License version 3, |
317 | + * as published by the Free Software Foundation. |
318 | + * |
319 | + * This program is distributed in the hope that it will be useful, |
320 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
321 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
322 | + * GNU Lesser General Public License for more details. |
323 | + * |
324 | + * You should have received a copy of the GNU Lesser General Public License |
325 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
326 | + * |
327 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
328 | + */ |
329 | + |
330 | +#include <core/media/apparmor/ubuntu.h> |
331 | + |
332 | +#include <core/media/external_services.h> |
333 | + |
334 | +#include <iostream> |
335 | +#include <regex> |
336 | + |
337 | +namespace apparmor = core::ubuntu::media::apparmor; |
338 | +namespace media = core::ubuntu::media; |
339 | +namespace ubuntu = apparmor::ubuntu; |
340 | + |
341 | +namespace |
342 | +{ |
343 | +struct Uri |
344 | +{ |
345 | + std::string scheme; |
346 | + std::string authority; |
347 | + std::string path; |
348 | + std::string query; |
349 | + std::string fragment; |
350 | +}; |
351 | + |
352 | +// Poor mans version of a uri parser. |
353 | +// See https://tools.ietf.org/html/rfc3986#appendix-B |
354 | +Uri parse_uri(const std::string& s) |
355 | +{ |
356 | + // Indices into the regex match go here. |
357 | + struct Index |
358 | + { |
359 | + const std::size_t scheme{2}; |
360 | + const std::size_t authority{4}; |
361 | + const std::size_t path{5}; |
362 | + const std::size_t query{7}; |
363 | + const std::size_t fragment{9}; |
364 | + } static index; |
365 | + |
366 | + static const std::regex regex{R"delim(^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)delim"}; |
367 | + std::smatch match; |
368 | + |
369 | + if (not std::regex_match(s, match, regex)) throw std::runtime_error |
370 | + { |
371 | + "Not a valid URI: " + s |
372 | + }; |
373 | + |
374 | + return Uri |
375 | + { |
376 | + match.str(index.scheme), |
377 | + match.str(index.authority), |
378 | + match.str(index.path), |
379 | + match.str(index.query), |
380 | + match.str(index.fragment) |
381 | + }; |
382 | +} |
383 | + |
384 | +static constexpr std::size_t index_package{1}; |
385 | +static constexpr std::size_t index_app{2}; |
386 | + |
387 | +// Returns true if the context name is a valid Ubuntu app id. |
388 | +// If it is, out is populated with the package and app name. |
389 | +bool process_context_name(const std::string& s, std::smatch& out) |
390 | +{ |
391 | + // See https://wiki.ubuntu.com/AppStore/Interfaces/ApplicationId. |
392 | + static const std::regex short_re{"(.*)_(.*)"}; |
393 | + static const std::regex full_re{"(.*)_(.*)_(.*)"}; |
394 | + |
395 | + if (std::regex_match(s, out, full_re)) |
396 | + return true; |
397 | + |
398 | + if (std::regex_match(s, out, short_re)) |
399 | + return true; |
400 | + |
401 | + return false; |
402 | +} |
403 | +} |
404 | + |
405 | +apparmor::ubuntu::Context::Context(const std::string& name) |
406 | + : apparmor::Context{name}, |
407 | + unconfined_{str() == ubuntu::unconfined}, |
408 | + has_package_name_{process_context_name(str(), match_)} |
409 | +{ |
410 | + if (not is_unconfined() && not has_package_name()) throw std::logic_error |
411 | + { |
412 | + "apparmor::ubuntu::Context: Invalid profile name " + str() |
413 | + }; |
414 | +} |
415 | + |
416 | +bool apparmor::ubuntu::Context::is_unconfined() const |
417 | +{ |
418 | + return unconfined_; |
419 | +} |
420 | + |
421 | +bool apparmor::ubuntu::Context::has_package_name() const |
422 | +{ |
423 | + return has_package_name_; |
424 | +} |
425 | + |
426 | + |
427 | +std::string apparmor::ubuntu::Context::package_name() const |
428 | +{ |
429 | + return std::string{match_[index_package]}; |
430 | +} |
431 | + |
432 | +apparmor::ubuntu::DBusDaemonRequestContextResolver::DBusDaemonRequestContextResolver(const core::dbus::Bus::Ptr& bus) : dbus_daemon{bus} |
433 | +{ |
434 | +} |
435 | + |
436 | +void apparmor::ubuntu::DBusDaemonRequestContextResolver::resolve_context_for_dbus_name_async( |
437 | + const std::string& name, |
438 | + apparmor::ubuntu::RequestContextResolver::ResolveCallback cb) |
439 | +{ |
440 | + dbus_daemon.get_connection_app_armor_security_async(name, [cb](const std::string& context_name) |
441 | + { |
442 | + cb(apparmor::ubuntu::Context{context_name}); |
443 | + }); |
444 | +} |
445 | + |
446 | +apparmor::ubuntu::RequestAuthenticator::Result apparmor::ubuntu::ExistingAuthenticator::authenticate_open_uri_request(const apparmor::ubuntu::Context& context, const std::string& uri) |
447 | +{ |
448 | + if (context.is_unconfined()) |
449 | + return Result{true, "Client allowed access since it's unconfined"}; |
450 | + |
451 | + Uri parsed_uri = parse_uri(uri); |
452 | + |
453 | + // All confined apps can access their own files |
454 | + if (parsed_uri.path.find(std::string(".local/share/" + context.package_name() + "/")) != std::string::npos || |
455 | + parsed_uri.path.find(std::string(".cache/" + context.package_name() + "/")) != std::string::npos) |
456 | + { |
457 | + return Result |
458 | + { |
459 | + true, |
460 | + "Client can access content in ~/.local/share/" + context.package_name() + " or ~/.cache/" + context.package_name() |
461 | + }; |
462 | + } |
463 | + else if (parsed_uri.path.find(std::string("opt/click.ubuntu.com/")) != std::string::npos && |
464 | + parsed_uri.path.find(context.package_name()) != std::string::npos) |
465 | + { |
466 | + return Result{true, "Client can access content in own opt directory"}; |
467 | + } |
468 | + else if ((parsed_uri.path.find(std::string("/system/media/audio/ui/")) != std::string::npos || |
469 | + parsed_uri.path.find(std::string("/android/system/media/audio/ui/")) != std::string::npos) && |
470 | + context.package_name() == "com.ubuntu.camera") |
471 | + { |
472 | + return Result{true, "Camera app can access ui sounds"}; |
473 | + } |
474 | + |
475 | + // TODO: Check if the trust store previously allowed direct access to uri |
476 | + |
477 | + // Check in ~/Music and ~/Videos |
478 | + // TODO: when the trust store lands, check it to see if this app can access the dirs and |
479 | + // then remove the explicit whitelist of the music-app, and gallery-app |
480 | + else if ((context.package_name() == "com.ubuntu.music" || context.package_name() == "com.ubuntu.gallery") && |
481 | + (parsed_uri.path.find(std::string("Music/")) != std::string::npos || |
482 | + parsed_uri.path.find(std::string("Videos/")) != std::string::npos || |
483 | + parsed_uri.path.find(std::string("/media")) != std::string::npos)) |
484 | + { |
485 | + return Result{true, "Client can access content in ~/Music or ~/Videos"}; |
486 | + } |
487 | + else if (parsed_uri.path.find(std::string("/usr/share/sounds")) != std::string::npos) |
488 | + { |
489 | + return Result{true, "Client can access content in /usr/share/sounds"}; |
490 | + } |
491 | + else if (parsed_uri.scheme == "http" || parsed_uri.scheme == "rtsp") |
492 | + { |
493 | + return Result{true, "Client can access streaming content"}; |
494 | + } |
495 | + |
496 | + return Result{false, "Client is not allowed to access: " + uri}; |
497 | +} |
498 | + |
499 | +// Returns the platform-default implementation of RequestContextResolver. |
500 | +apparmor::ubuntu::RequestContextResolver::Ptr apparmor::ubuntu::make_platform_default_request_context_resolver(media::helper::ExternalServices& es) |
501 | +{ |
502 | + return std::make_shared<apparmor::ubuntu::DBusDaemonRequestContextResolver>(es.session); |
503 | +} |
504 | + |
505 | +// Returns the platform-default implementation of RequestAuthenticator. |
506 | +apparmor::ubuntu::RequestAuthenticator::Ptr apparmor::ubuntu::make_platform_default_request_authenticator() |
507 | +{ |
508 | + return std::make_shared<apparmor::ubuntu::ExistingAuthenticator>(); |
509 | +} |
510 | |
511 | === added file 'src/core/media/apparmor/ubuntu.h' |
512 | --- src/core/media/apparmor/ubuntu.h 1970-01-01 00:00:00 +0000 |
513 | +++ src/core/media/apparmor/ubuntu.h 2015-03-12 11:45:23 +0000 |
514 | @@ -0,0 +1,167 @@ |
515 | +/* |
516 | + * Copyright © 2014 Canonical Ltd. |
517 | + * |
518 | + * This program is free software: you can redistribute it and/or modify it |
519 | + * under the terms of the GNU Lesser General Public License version 3, |
520 | + * as published by the Free Software Foundation. |
521 | + * |
522 | + * This program is distributed in the hope that it will be useful, |
523 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
524 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
525 | + * GNU Lesser General Public License for more details. |
526 | + * |
527 | + * You should have received a copy of the GNU Lesser General Public License |
528 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
529 | + * |
530 | + * Authored by: Thomas Voß <thomas.voss@canonical.com> |
531 | + */ |
532 | +#ifndef CORE_UBUNTU_MEDIA_APPARMOR_UBUNTU_H_ |
533 | +#define CORE_UBUNTU_MEDIA_APPARMOR_UBUNTU_H_ |
534 | + |
535 | +#include <core/media/apparmor/context.h> |
536 | +#include <core/media/apparmor/dbus.h> |
537 | + |
538 | +#include <functional> |
539 | +#include <memory> |
540 | +#include <regex> |
541 | +#include <string> |
542 | +#include <vector> |
543 | + |
544 | +namespace core |
545 | +{ |
546 | +namespace dbus |
547 | +{ |
548 | +class Bus; |
549 | +} |
550 | + |
551 | +namespace ubuntu |
552 | +{ |
553 | +namespace media |
554 | +{ |
555 | +namespace helper |
556 | +{ |
557 | +struct ExternalServices; |
558 | +} |
559 | +namespace apparmor |
560 | +{ |
561 | +// Collects Ubuntu-specific apparmor conventions, e.g., format |
562 | +// of short and full package names as well as convenience functionality |
563 | +// to inspect apparmor::Context instances. |
564 | +namespace ubuntu |
565 | +{ |
566 | +// The unconfined profile, unconditionally trusted |
567 | +// by the system. |
568 | +static constexpr const char* unconfined |
569 | +{ |
570 | + "unconfined" |
571 | +}; |
572 | + |
573 | +class Context : public apparmor::Context |
574 | +{ |
575 | +public: |
576 | + // Constructs a new Context instance for the given raw name. |
577 | + // Throws std::logic_error for empty names or for names not |
578 | + // complying to Ubuntu conventions. |
579 | + Context(const std::string& name); |
580 | + |
581 | + // Returns true iff the context is unconfined. |
582 | + virtual bool is_unconfined() const; |
583 | + |
584 | + // Returns true iff the context contains a package name. |
585 | + virtual bool has_package_name() const; |
586 | + |
587 | + // Returns the package name or throws if no package name can be found. |
588 | + virtual std::string package_name() const; |
589 | + |
590 | +private: |
591 | + std::smatch match_; |
592 | + const bool unconfined_; |
593 | + const bool has_package_name_; |
594 | +}; |
595 | + |
596 | +// Abstracts query for the apparmor context of an incoming request |
597 | +class RequestContextResolver |
598 | +{ |
599 | +public: |
600 | + // To save us some typing. |
601 | + typedef std::shared_ptr<RequestContextResolver> Ptr; |
602 | + |
603 | + // Callback for resolve context operations. |
604 | + typedef std::function<void(const Context&)> ResolveCallback; |
605 | + |
606 | + // Resolves the given name (of a dbus participant) to its apparmor context, |
607 | + // invoking the callback whenever a result is available. |
608 | + virtual void resolve_context_for_dbus_name_async(const std::string& name, ResolveCallback cb) = 0; |
609 | + |
610 | +protected: |
611 | + RequestContextResolver() = default; |
612 | + RequestContextResolver(const RequestContextResolver&) = delete; |
613 | + virtual ~RequestContextResolver() = default; |
614 | + RequestContextResolver& operator=(const RequestContextResolver&) = delete; |
615 | +}; |
616 | + |
617 | +// An implementation of RequestContextResolver that queries the dbus |
618 | +// daemon to resolve the apparmor context. |
619 | +class DBusDaemonRequestContextResolver : public RequestContextResolver |
620 | +{ |
621 | +public: |
622 | + // To save us some typing. |
623 | + typedef std::shared_ptr<DBusDaemonRequestContextResolver> Ptr; |
624 | + |
625 | + // Constructs a new instance for the given bus connection. |
626 | + DBusDaemonRequestContextResolver(const core::dbus::Bus::Ptr &); |
627 | + |
628 | + // From RequestContextResolver |
629 | + void resolve_context_for_dbus_name_async(const std::string& name, ResolveCallback) override; |
630 | + |
631 | +private: |
632 | + org::freedesktop::dbus::DBus::Stub dbus_daemon; |
633 | +}; |
634 | + |
635 | +// Abstracts an apparmor-based authentication of |
636 | +// incoming requests from clients. |
637 | +class RequestAuthenticator |
638 | +{ |
639 | +public: |
640 | + // To save us some typing. |
641 | + typedef std::shared_ptr<RequestAuthenticator> Ptr; |
642 | + |
643 | + // Return type of an authentication call. |
644 | + typedef std::tuple |
645 | + < |
646 | + bool, // True if authenticated, false if not. |
647 | + std::string // Reason for the result. |
648 | + > Result; |
649 | + |
650 | + virtual ~RequestAuthenticator() = default; |
651 | + |
652 | + // Returns true iff the client identified by the given apparmor::Context is allowed |
653 | + // to access the given uri, false otherwise. |
654 | + virtual Result authenticate_open_uri_request(const Context&, const std::string& uri) = 0; |
655 | + |
656 | +protected: |
657 | + RequestAuthenticator() = default; |
658 | + RequestAuthenticator(const RequestAuthenticator&) = default; |
659 | + RequestAuthenticator& operator=(const RequestAuthenticator&) = default; |
660 | +}; |
661 | + |
662 | +// Takes the existing logic and exposes it as an implementation |
663 | +// of the RequestAuthenticator interface. |
664 | +struct ExistingAuthenticator : public RequestAuthenticator |
665 | +{ |
666 | + ExistingAuthenticator() = default; |
667 | + // From RequestAuthenticator |
668 | + Result authenticate_open_uri_request(const Context&, const std::string& uri) override; |
669 | +}; |
670 | + |
671 | +// Returns the platform-default implementation of RequestContextResolver. |
672 | +RequestContextResolver::Ptr make_platform_default_request_context_resolver(helper::ExternalServices& es); |
673 | +// Returns the platform-default implementation of RequestAuthenticator. |
674 | +RequestAuthenticator::Ptr make_platform_default_request_authenticator(); |
675 | +} |
676 | +} |
677 | +} |
678 | +} |
679 | +} |
680 | + |
681 | +#endif // CORE_UBUNTU_MEDIA_APPARMOR_UBUNTU_H_ |
682 | |
683 | === modified file 'src/core/media/player.cpp' |
684 | --- src/core/media/player.cpp 2015-03-12 11:45:23 +0000 |
685 | +++ src/core/media/player.cpp 2015-03-12 11:45:23 +0000 |
686 | @@ -31,7 +31,6 @@ |
687 | { |
688 | static const media::Player::Configuration config |
689 | { |
690 | - std::string{""}, |
691 | 0, |
692 | nullptr, |
693 | nullptr |
694 | |
695 | === modified file 'src/core/media/player_configuration.h' |
696 | --- src/core/media/player_configuration.h 2014-09-09 10:28:32 +0000 |
697 | +++ src/core/media/player_configuration.h 2015-03-12 11:45:23 +0000 |
698 | @@ -27,9 +27,6 @@ |
699 | // to the implementation in a way that is opaque to the client. |
700 | struct core::ubuntu::media::Player::Configuration |
701 | { |
702 | - // An identifier that is helpful in referencing the player instance |
703 | - // across multiple services. |
704 | - std::string identity; |
705 | // Unique key for identifying the session. |
706 | core::ubuntu::media::Player::PlayerKey key; |
707 | // The bus connection to expose objects on. |
708 | |
709 | === modified file 'src/core/media/player_implementation.cpp' |
710 | --- src/core/media/player_implementation.cpp 2015-03-12 11:45:23 +0000 |
711 | +++ src/core/media/player_implementation.cpp 2015-03-12 11:45:23 +0000 |
712 | @@ -293,7 +293,8 @@ |
713 | { |
714 | config.bus, |
715 | config.session, |
716 | - config.identity |
717 | + config.request_context_resolver, |
718 | + config.request_authenticator |
719 | } |
720 | }, |
721 | d{std::make_shared<Private>(this, config)} |
722 | |
723 | === modified file 'src/core/media/player_implementation.h' |
724 | --- src/core/media/player_implementation.h 2015-03-12 11:45:23 +0000 |
725 | +++ src/core/media/player_implementation.h 2015-03-12 11:45:23 +0000 |
726 | @@ -21,6 +21,7 @@ |
727 | |
728 | #include "player_skeleton.h" |
729 | |
730 | +#include "apparmor/ubuntu.h" |
731 | #include "client_death_observer.h" |
732 | #include "power/state_controller.h" |
733 | |
734 | @@ -41,13 +42,14 @@ |
735 | // All creation time arguments go here |
736 | struct Configuration |
737 | { |
738 | - std::string identity; |
739 | std::shared_ptr<core::dbus::Bus> bus; |
740 | std::shared_ptr<core::dbus::Object> session; |
741 | std::shared_ptr<Service> service; |
742 | PlayerKey key; |
743 | |
744 | // Functional dependencies |
745 | + apparmor::ubuntu::RequestContextResolver::Ptr request_context_resolver; |
746 | + apparmor::ubuntu::RequestAuthenticator::Ptr request_authenticator; |
747 | ClientDeathObserver::Ptr client_death_observer; |
748 | power::StateController::Ptr power_state_controller; |
749 | }; |
750 | |
751 | === modified file 'src/core/media/player_skeleton.cpp' |
752 | --- src/core/media/player_skeleton.cpp 2015-03-12 11:45:23 +0000 |
753 | +++ src/core/media/player_skeleton.cpp 2015-03-12 11:45:23 +0000 |
754 | @@ -17,15 +17,16 @@ |
755 | * Jim Hodapp <jim.hodapp@canonical.com> |
756 | */ |
757 | |
758 | -#include "apparmor.h" |
759 | #include "codec.h" |
760 | #include "engine.h" |
761 | +#include "external_services.h" |
762 | #include "player_skeleton.h" |
763 | #include "player_traits.h" |
764 | #include "property_stub.h" |
765 | #include "the_session_bus.h" |
766 | #include "xesam.h" |
767 | |
768 | +#include "apparmor/ubuntu.h" |
769 | #include "mpris/media_player2.h" |
770 | #include "mpris/metadata.h" |
771 | #include "mpris/player.h" |
772 | @@ -44,15 +45,15 @@ |
773 | struct media::PlayerSkeleton::Private |
774 | { |
775 | Private(media::PlayerSkeleton* player, |
776 | - const std::string& identity, |
777 | const std::shared_ptr<core::dbus::Bus>& bus, |
778 | - const std::shared_ptr<core::dbus::Object>& session) |
779 | + const std::shared_ptr<core::dbus::Object>& session, |
780 | + const apparmor::ubuntu::RequestContextResolver::Ptr& request_context_resolver, |
781 | + const apparmor::ubuntu::RequestAuthenticator::Ptr& request_authenticator) |
782 | : impl(player), |
783 | - identity(identity), |
784 | bus(bus), |
785 | object(session), |
786 | - apparmor_session(nullptr), |
787 | - dbus_stub{bus}, |
788 | + request_context_resolver{request_context_resolver}, |
789 | + request_authenticator{request_authenticator}, |
790 | skeleton{mpris::Player::Skeleton::Configuration{bus, session, mpris::Player::Skeleton::Configuration::Defaults{}}}, |
791 | signals |
792 | { |
793 | @@ -163,82 +164,6 @@ |
794 | bus->send(reply); |
795 | } |
796 | |
797 | - bool does_client_have_access(const std::string& context, const std::string& uri) |
798 | - { |
799 | - if (context.empty() || uri.empty()) |
800 | - { |
801 | - std::cout << "Client denied access since context or uri are empty" << std::endl; |
802 | - return false; |
803 | - } |
804 | - |
805 | - if (context == "unconfined") |
806 | - { |
807 | - std::cout << "Client allowed access since it's unconfined" << std::endl; |
808 | - return true; |
809 | - } |
810 | - |
811 | - size_t pos = context.find_first_of('_'); |
812 | - if (pos == std::string::npos) |
813 | - { |
814 | - std::cout << "Client denied access since it's an invalid apparmor security context" << std::endl; |
815 | - return false; |
816 | - } |
817 | - |
818 | - const std::string pkgname = context.substr(0, pos); |
819 | - std::cout << "client pkgname: " << pkgname << std::endl; |
820 | - std::cout << "uri: " << uri << std::endl; |
821 | - |
822 | - // All confined apps can access their own files |
823 | - if (uri.find(std::string(".local/share/" + pkgname + "/")) != std::string::npos |
824 | - || uri.find(std::string(".cache/" + pkgname + "/")) != std::string::npos) |
825 | - { |
826 | - std::cout << "Client can access content in ~/.local/share/" << pkgname << " or ~/.cache/" << pkgname << std::endl; |
827 | - return true; |
828 | - } |
829 | - else if (uri.find(std::string("opt/click.ubuntu.com/")) != std::string::npos |
830 | - && uri.find(pkgname) != std::string::npos) |
831 | - { |
832 | - std::cout << "Client can access content in own opt directory" << std::endl; |
833 | - return true; |
834 | - } |
835 | - else if ((uri.find(std::string("/system/media/audio/ui/")) != std::string::npos |
836 | - || uri.find(std::string("/android/system/media/audio/ui/")) != std::string::npos) |
837 | - && pkgname == "com.ubuntu.camera") |
838 | - { |
839 | - std::cout << "Camera app can access ui sounds" << std::endl; |
840 | - return true; |
841 | - } |
842 | - // TODO: Check if the trust store previously allowed direct access to uri |
843 | - |
844 | - // Check in ~/Music and ~/Videos |
845 | - // TODO: when the trust store lands, check it to see if this app can access the dirs and |
846 | - // then remove the explicit whitelist of the music-app, and gallery-app |
847 | - else if ((pkgname == "com.ubuntu.music" || pkgname == "com.ubuntu.gallery") && |
848 | - (uri.find(std::string("Music/")) != std::string::npos |
849 | - || uri.find(std::string("Videos/")) != std::string::npos |
850 | - || uri.find(std::string("/media")) != std::string::npos)) |
851 | - { |
852 | - std::cout << "Client can access content in ~/Music or ~/Videos" << std::endl; |
853 | - return true; |
854 | - } |
855 | - else if (uri.find(std::string("/usr/share/sounds")) != std::string::npos) |
856 | - { |
857 | - std::cout << "Client can access content in /usr/share/sounds" << std::endl; |
858 | - return true; |
859 | - } |
860 | - else if (uri.find(std::string("http://")) != std::string::npos |
861 | - || uri.find(std::string("rtsp://")) != std::string::npos) |
862 | - { |
863 | - std::cout << "Client can access streaming content" << std::endl; |
864 | - return true; |
865 | - } |
866 | - else |
867 | - { |
868 | - std::cout << "Client denied access to open_uri()" << std::endl; |
869 | - return false; |
870 | - } |
871 | - } |
872 | - |
873 | void handle_key(const core::dbus::Message::Ptr& in) |
874 | { |
875 | auto reply = dbus::Message::make_method_return(in); |
876 | @@ -248,15 +173,15 @@ |
877 | |
878 | void handle_open_uri(const core::dbus::Message::Ptr& in) |
879 | { |
880 | - dbus_stub.get_connection_app_armor_security_async(in->sender(), [this, in](const std::string& profile) |
881 | + request_context_resolver->resolve_context_for_dbus_name_async(in->sender(), [this, in](const media::apparmor::ubuntu::Context& context) |
882 | { |
883 | Track::UriType uri; |
884 | in->reader() >> uri; |
885 | |
886 | - bool have_access = does_client_have_access(profile, uri); |
887 | + auto result = request_authenticator->authenticate_open_uri_request(context, uri); |
888 | |
889 | auto reply = dbus::Message::make_method_return(in); |
890 | - reply->writer() << (have_access ? impl->open_uri(uri) : false); |
891 | + reply->writer() << (std::get<0>(result) ? impl->open_uri(uri) : false); |
892 | |
893 | bus->send(reply); |
894 | }); |
895 | @@ -264,16 +189,16 @@ |
896 | |
897 | void handle_open_uri_extended(const core::dbus::Message::Ptr& in) |
898 | { |
899 | - dbus_stub.get_connection_app_armor_security_async(in->sender(), [this, in](const std::string& profile) |
900 | + request_context_resolver->resolve_context_for_dbus_name_async(in->sender(), [this, in](const media::apparmor::ubuntu::Context& context) |
901 | { |
902 | Track::UriType uri; |
903 | Player::HeadersType headers; |
904 | |
905 | in->reader() >> uri >> headers; |
906 | |
907 | - bool have_access = does_client_have_access(profile, uri); |
908 | + auto result = request_authenticator->authenticate_open_uri_request(context, uri); |
909 | auto reply = dbus::Message::make_method_return(in); |
910 | - reply->writer() << (have_access ? impl->open_uri(uri, headers) : false); |
911 | + reply->writer() << (std::get<0>(result) ? impl->open_uri(uri, headers) : false); |
912 | |
913 | bus->send(reply); |
914 | }); |
915 | @@ -301,12 +226,10 @@ |
916 | } |
917 | |
918 | media::PlayerSkeleton* impl; |
919 | - std::string identity; |
920 | dbus::Bus::Ptr bus; |
921 | dbus::Object::Ptr object; |
922 | - dbus::Object::Ptr apparmor_session; |
923 | - |
924 | - org::freedesktop::dbus::DBus::Stub dbus_stub; |
925 | + media::apparmor::ubuntu::RequestContextResolver::Ptr request_context_resolver; |
926 | + media::apparmor::ubuntu::RequestAuthenticator::Ptr request_authenticator; |
927 | |
928 | mpris::Player::Skeleton skeleton; |
929 | |
930 | @@ -360,7 +283,7 @@ |
931 | }; |
932 | |
933 | media::PlayerSkeleton::PlayerSkeleton(const media::PlayerSkeleton::Configuration& config) |
934 | - : d(new Private{this, config.identity, config.bus, config.session}) |
935 | + : d(new Private{this, config.bus, config.session, config.request_context_resolver, config.request_authenticator}) |
936 | { |
937 | // Setup method handlers for mpris::Player methods. |
938 | auto next = std::bind(&Private::handle_next, d, std::placeholders::_1); |
939 | |
940 | === modified file 'src/core/media/player_skeleton.h' |
941 | --- src/core/media/player_skeleton.h 2015-03-12 11:45:23 +0000 |
942 | +++ src/core/media/player_skeleton.h 2015-03-12 11:45:23 +0000 |
943 | @@ -24,6 +24,7 @@ |
944 | |
945 | #include "player_traits.h" |
946 | |
947 | +#include "apparmor/ubuntu.h" |
948 | #include "mpris/player.h" |
949 | |
950 | #include <core/dbus/skeleton.h> |
951 | @@ -37,6 +38,11 @@ |
952 | { |
953 | namespace media |
954 | { |
955 | +namespace helper |
956 | +{ |
957 | +struct ExternalServices; |
958 | +} |
959 | + |
960 | class Service; |
961 | |
962 | class PlayerSkeleton : public core::ubuntu::media::Player |
963 | @@ -86,9 +92,9 @@ |
964 | std::shared_ptr<core::dbus::Bus> bus; |
965 | // The session object that we want to expose the skeleton upon. |
966 | std::shared_ptr<core::dbus::Object> session; |
967 | - // Our identity, an identifier we pass out to other parts of the system. |
968 | - // Defaults to the short app id (${PKG_NAME}_${APP}). |
969 | - std::string identity; |
970 | + // Our functional dependencies. |
971 | + apparmor::ubuntu::RequestContextResolver::Ptr request_context_resolver; |
972 | + apparmor::ubuntu::RequestAuthenticator::Ptr request_authenticator; |
973 | }; |
974 | |
975 | PlayerSkeleton(const Configuration& configuration); |
976 | |
977 | === modified file 'src/core/media/service_implementation.cpp' |
978 | --- src/core/media/service_implementation.cpp 2015-03-12 11:45:23 +0000 |
979 | +++ src/core/media/service_implementation.cpp 2015-03-12 11:45:23 +0000 |
980 | @@ -22,6 +22,7 @@ |
981 | |
982 | #include "service_implementation.h" |
983 | |
984 | +#include "apparmor/ubuntu.h" |
985 | #include "audio/output_observer.h" |
986 | #include "client_death_observer.h" |
987 | #include "player_configuration.h" |
988 | @@ -59,6 +60,8 @@ |
989 | client_death_observer(media::platform_default_client_death_observer()), |
990 | recorder_observer(media::make_platform_default_recorder_observer()), |
991 | audio_output_observer(media::audio::make_platform_default_output_observer()), |
992 | + request_context_resolver(media::apparmor::ubuntu::make_platform_default_request_context_resolver(configuration.external_services)), |
993 | + request_authenticator(media::apparmor::ubuntu::make_platform_default_request_authenticator()), |
994 | audio_output_state(media::audio::OutputState::Speaker), |
995 | call_monitor(media::telephony::make_platform_default_call_monitor()) |
996 | { |
997 | @@ -74,13 +77,16 @@ |
998 | media::ClientDeathObserver::Ptr client_death_observer; |
999 | media::RecorderObserver::Ptr recorder_observer; |
1000 | media::audio::OutputObserver::Ptr audio_output_observer; |
1001 | + media::apparmor::ubuntu::RequestContextResolver::Ptr request_context_resolver; |
1002 | + media::apparmor::ubuntu::RequestAuthenticator::Ptr request_authenticator; |
1003 | media::audio::OutputState audio_output_state; |
1004 | |
1005 | media::telephony::CallMonitor::Ptr call_monitor; |
1006 | std::list<media::Player::PlayerKey> paused_sessions; |
1007 | }; |
1008 | |
1009 | -media::ServiceImplementation::ServiceImplementation(const Configuration& configuration) : d(new Private(configuration)) |
1010 | +media::ServiceImplementation::ServiceImplementation(const Configuration& configuration) |
1011 | + : d(new Private(configuration)) |
1012 | { |
1013 | d->battery_observer->level().changed().connect([this](const media::power::Level& level) |
1014 | { |
1015 | @@ -160,11 +166,12 @@ |
1016 | { |
1017 | auto player = std::make_shared<media::PlayerImplementation>(media::PlayerImplementation::Configuration |
1018 | { |
1019 | - conf.identity, |
1020 | conf.bus, |
1021 | conf.session, |
1022 | shared_from_this(), |
1023 | conf.key, |
1024 | + d->request_context_resolver, |
1025 | + d->request_authenticator, |
1026 | d->client_death_observer, |
1027 | d->power_state_controller |
1028 | }); |
1029 | |
1030 | === modified file 'src/core/media/service_skeleton.cpp' |
1031 | --- src/core/media/service_skeleton.cpp 2014-11-18 20:29:26 +0000 |
1032 | +++ src/core/media/service_skeleton.cpp 2015-03-12 11:45:23 +0000 |
1033 | @@ -19,8 +19,6 @@ |
1034 | |
1035 | #include "service_skeleton.h" |
1036 | |
1037 | -#include "apparmor.h" |
1038 | - |
1039 | #include "mpris/media_player2.h" |
1040 | #include "mpris/metadata.h" |
1041 | #include "mpris/player.h" |
1042 | @@ -55,7 +53,6 @@ |
1043 | : impl(impl), |
1044 | object(impl->access_service()->add_object_for_path( |
1045 | dbus::traits::Service<media::Service>::object_path())), |
1046 | - dbus_stub(impl->access_bus()), |
1047 | exported(impl->access_bus(), resolver) |
1048 | { |
1049 | object->install_method_handler<mpris::Service::CreateSession>( |
1050 | @@ -99,19 +96,61 @@ |
1051 | dbus::types::ObjectPath op{session_info.first}; |
1052 | media::Player::PlayerKey key{session_info.second}; |
1053 | |
1054 | - dbus_stub.get_connection_app_armor_security_async(msg->sender(), [this, msg, op, key](const std::string& profile) |
1055 | - { |
1056 | - media::Player::Configuration config |
1057 | - { |
1058 | - profile, |
1059 | - key, |
1060 | - impl->access_bus(), |
1061 | - impl->access_service()->add_object_for_path(op) |
1062 | - }; |
1063 | - |
1064 | - try |
1065 | - { |
1066 | + media::Player::Configuration config |
1067 | + { |
1068 | + key, |
1069 | + impl->access_bus(), |
1070 | + impl->access_service()->add_object_for_path(op) |
1071 | + }; |
1072 | + |
1073 | + try |
1074 | + { |
1075 | + auto session = impl->create_session(config); |
1076 | + |
1077 | + bool inserted = false; |
1078 | + std::tie(std::ignore, inserted) |
1079 | + = session_store.insert(std::make_pair(key, session)); |
1080 | + |
1081 | + if (!inserted) |
1082 | + throw std::runtime_error("Problem persisting session in session store."); |
1083 | + |
1084 | + auto reply = dbus::Message::make_method_return(msg); |
1085 | + reply->writer() << op; |
1086 | + |
1087 | + impl->access_bus()->send(reply); |
1088 | + } catch(const std::runtime_error& e) |
1089 | + { |
1090 | + auto reply = dbus::Message::make_error( |
1091 | + msg, |
1092 | + mpris::Service::Errors::CreatingSession::name(), |
1093 | + e.what()); |
1094 | + impl->access_bus()->send(reply); |
1095 | + } |
1096 | + } |
1097 | + |
1098 | + void handle_create_fixed_session(const core::dbus::Message::Ptr& msg) |
1099 | + { |
1100 | + try |
1101 | + { |
1102 | + std::string name; |
1103 | + msg->reader() >> name; |
1104 | + |
1105 | + if (fixed_session_store.count(name) == 0) { |
1106 | + // Create new session |
1107 | + auto session_info = create_session_info(); |
1108 | + |
1109 | + dbus::types::ObjectPath op{session_info.first}; |
1110 | + media::Player::PlayerKey key{session_info.second}; |
1111 | + |
1112 | + media::Player::Configuration config |
1113 | + { |
1114 | + key, |
1115 | + impl->access_bus(), |
1116 | + impl->access_service()->add_object_for_path(op) |
1117 | + }; |
1118 | + |
1119 | auto session = impl->create_session(config); |
1120 | + session->lifetime().set(media::Player::Lifetime::resumable); |
1121 | |
1122 | bool inserted = false; |
1123 | std::tie(std::ignore, inserted) |
1124 | @@ -120,108 +159,20 @@ |
1125 | if (!inserted) |
1126 | throw std::runtime_error("Problem persisting session in session store."); |
1127 | |
1128 | + fixed_session_store.insert(std::make_pair(name, key)); |
1129 | |
1130 | auto reply = dbus::Message::make_method_return(msg); |
1131 | reply->writer() << op; |
1132 | |
1133 | impl->access_bus()->send(reply); |
1134 | - } catch(const std::runtime_error& e) |
1135 | - { |
1136 | - auto reply = dbus::Message::make_error( |
1137 | - msg, |
1138 | - mpris::Service::Errors::CreatingSession::name(), |
1139 | - e.what()); |
1140 | - impl->access_bus()->send(reply); |
1141 | - } |
1142 | - }); |
1143 | - } |
1144 | - |
1145 | - void handle_create_fixed_session(const core::dbus::Message::Ptr& msg) |
1146 | - { |
1147 | - dbus_stub.get_connection_app_armor_security_async(msg->sender(), [this, msg](const std::string& profile) |
1148 | - { |
1149 | - try |
1150 | - { |
1151 | - std::string name; |
1152 | - msg->reader() >> name; |
1153 | - |
1154 | - if (fixed_session_store.count(name) == 0) { |
1155 | - // Create new session |
1156 | - auto session_info = create_session_info(); |
1157 | - |
1158 | - dbus::types::ObjectPath op{session_info.first}; |
1159 | - media::Player::PlayerKey key{session_info.second}; |
1160 | - |
1161 | - media::Player::Configuration config |
1162 | - { |
1163 | - profile, |
1164 | - key, |
1165 | - impl->access_bus(), |
1166 | - impl->access_service()->add_object_for_path(op) |
1167 | - }; |
1168 | - |
1169 | - auto session = impl->create_session(config); |
1170 | - session->lifetime().set(media::Player::Lifetime::resumable); |
1171 | - |
1172 | - bool inserted = false; |
1173 | - std::tie(std::ignore, inserted) |
1174 | - = session_store.insert(std::make_pair(key, session)); |
1175 | - |
1176 | - if (!inserted) |
1177 | - throw std::runtime_error("Problem persisting session in session store."); |
1178 | - |
1179 | - fixed_session_store.insert(std::make_pair(name, key)); |
1180 | - |
1181 | - auto reply = dbus::Message::make_method_return(msg); |
1182 | - reply->writer() << op; |
1183 | - |
1184 | - impl->access_bus()->send(reply); |
1185 | - } |
1186 | - else { |
1187 | - // Resume previous session |
1188 | - auto key = fixed_session_store[name]; |
1189 | - if (session_store.count(key) == 0) { |
1190 | - auto reply = dbus::Message::make_error( |
1191 | - msg, |
1192 | - mpris::Service::Errors::CreatingFixedSession::name(), |
1193 | - "Unable to locate player session"); |
1194 | - impl->access_bus()->send(reply); |
1195 | - return; |
1196 | - } |
1197 | - |
1198 | - std::stringstream ss; |
1199 | - ss << "/core/ubuntu/media/Service/sessions/" << key; |
1200 | - dbus::types::ObjectPath op{ss.str()}; |
1201 | - |
1202 | - auto reply = dbus::Message::make_method_return(msg); |
1203 | - reply->writer() << op; |
1204 | - |
1205 | - impl->access_bus()->send(reply); |
1206 | - } |
1207 | - } catch(const std::runtime_error& e) |
1208 | - { |
1209 | - auto reply = dbus::Message::make_error( |
1210 | - msg, |
1211 | - mpris::Service::Errors::CreatingSession::name(), |
1212 | - e.what()); |
1213 | - impl->access_bus()->send(reply); |
1214 | - } |
1215 | - }); |
1216 | - } |
1217 | - |
1218 | - void handle_resume_session(const core::dbus::Message::Ptr& msg) |
1219 | - { |
1220 | - dbus_stub.get_connection_app_armor_security_async(msg->sender(), [this, msg](const std::string&) |
1221 | - { |
1222 | - try |
1223 | - { |
1224 | - Player::PlayerKey key; |
1225 | - msg->reader() >> key; |
1226 | - |
1227 | + } |
1228 | + else { |
1229 | + // Resume previous session |
1230 | + auto key = fixed_session_store[name]; |
1231 | if (session_store.count(key) == 0) { |
1232 | auto reply = dbus::Message::make_error( |
1233 | msg, |
1234 | - mpris::Service::Errors::ResumingSession::name(), |
1235 | + mpris::Service::Errors::CreatingFixedSession::name(), |
1236 | "Unable to locate player session"); |
1237 | impl->access_bus()->send(reply); |
1238 | return; |
1239 | @@ -235,15 +186,49 @@ |
1240 | reply->writer() << op; |
1241 | |
1242 | impl->access_bus()->send(reply); |
1243 | - } catch(const std::runtime_error& e) |
1244 | - { |
1245 | + } |
1246 | + } catch(const std::runtime_error& e) |
1247 | + { |
1248 | + auto reply = dbus::Message::make_error( |
1249 | + msg, |
1250 | + mpris::Service::Errors::CreatingSession::name(), |
1251 | + e.what()); |
1252 | + impl->access_bus()->send(reply); |
1253 | + } |
1254 | + } |
1255 | + |
1256 | + void handle_resume_session(const core::dbus::Message::Ptr& msg) |
1257 | + { |
1258 | + try |
1259 | + { |
1260 | + Player::PlayerKey key; |
1261 | + msg->reader() >> key; |
1262 | + |
1263 | + if (session_store.count(key) == 0) { |
1264 | auto reply = dbus::Message::make_error( |
1265 | msg, |
1266 | - mpris::Service::Errors::CreatingSession::name(), |
1267 | - e.what()); |
1268 | + mpris::Service::Errors::ResumingSession::name(), |
1269 | + "Unable to locate player session"); |
1270 | impl->access_bus()->send(reply); |
1271 | + return; |
1272 | } |
1273 | - }); |
1274 | + |
1275 | + std::stringstream ss; |
1276 | + ss << "/core/ubuntu/media/Service/sessions/" << key; |
1277 | + dbus::types::ObjectPath op{ss.str()}; |
1278 | + |
1279 | + auto reply = dbus::Message::make_method_return(msg); |
1280 | + reply->writer() << op; |
1281 | + |
1282 | + impl->access_bus()->send(reply); |
1283 | + } catch(const std::runtime_error& e) |
1284 | + { |
1285 | + auto reply = dbus::Message::make_error( |
1286 | + msg, |
1287 | + mpris::Service::Errors::CreatingSession::name(), |
1288 | + e.what()); |
1289 | + impl->access_bus()->send(reply); |
1290 | + } |
1291 | } |
1292 | |
1293 | void handle_pause_other_sessions(const core::dbus::Message::Ptr& msg) |
1294 | @@ -260,8 +245,6 @@ |
1295 | media::ServiceSkeleton* impl; |
1296 | dbus::Object::Ptr object; |
1297 | |
1298 | - // We query the apparmor profile to obtain an identity for players. |
1299 | - org::freedesktop::dbus::DBus::Stub dbus_stub; |
1300 | // We track all running player instances. |
1301 | std::map<media::Player::PlayerKey, std::shared_ptr<media::Player>> session_store; |
1302 | std::map<std::string, media::Player::PlayerKey> fixed_session_store; |
FAILED: Continuous integration, rev:111 jenkins. qa.ubuntu. com/job/ media-hub- ci/194/ jenkins. qa.ubuntu. com/job/ media-hub- vivid-amd64- ci/34/console jenkins. qa.ubuntu. com/job/ media-hub- vivid-armhf- ci/34/console jenkins. qa.ubuntu. com/job/ media-hub- vivid-i386- ci/34/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/media- hub-ci/ 194/rebuild
http://