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