Merge lp:~phablet-team/media-hub/introduce-apparmor-interfaces into lp:media-hub

Proposed by Ricardo Salveti
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
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::ubuntu::RequestAuthenticator that is used to authenticate incoming open uri requests.
Add an interface apparmor::ubuntu::RequestContextResolver that is used to resolve a dbus name to an apparmor::ubuntu::Context.
Provide an implementation apparmor::ubuntu::ExistingAuthenticator that takes the impl. from player_skeleton.cpp and uses it to implement the interface.
Provide an implementation apparmor::ubuntu::RequestContextResolver that reaches out to the dbus daemon to resolve a given bus name to an apparmor profile.
Remove obsolete query for the apparmor profile in ServiceSkeleton.
Adjust the implementation in media::PlayerSkeleton to rely on Request{Authenticator, ContextResolver}.

Description of the change

Add an interface apparmor::ubuntu::RequestAuthenticator that is used to authenticate incoming open uri requests.
Add an interface apparmor::ubuntu::RequestContextResolver that is used to resolve a dbus name to an apparmor::ubuntu::Context.
Provide an implementation apparmor::ubuntu::ExistingAuthenticator that takes the impl. from player_skeleton.cpp and uses it to implement the interface.
Provide an implementation apparmor::ubuntu::RequestContextResolver that reaches out to the dbus daemon to resolve a given bus name to an apparmor profile.
Remove obsolete query for the apparmor profile in ServiceSkeleton.
Adjust the implementation in media::PlayerSkeleton to rely on Request{Authenticator, ContextResolver}.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Jim Hodapp (jhodapp) wrote : Posted in a previous version of this proposal

One simple comment below.

review: Needs Fixing (code)
Revision history for this message
Thomas Voß (thomas-voss) : Posted in a previous version of this proposal
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
121. By Ricardo Salveti

Merge prereq

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
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

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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 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-04 18:32:01 +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-04 18:32:01 +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-04 18:32:01 +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-04 18:32:01 +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-04 18:32:01 +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-04 18:32:01 +0000
685+++ src/core/media/player.cpp 2015-03-04 18:32:01 +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-04 18:32:01 +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-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 {
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-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
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-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 * 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-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
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-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
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::audio::OutputObserver audio_output_state;
1002+ media::apparmor::ubuntu::RequestContextResolver::Ptr request_context_resolver;
1003+ media::apparmor::ubuntu::RequestAuthenticator::Ptr request_authenticator;
1004+ media::audio::OutputState audio_output_state;
1005
1006 media::telephony::CallMonitor::Ptr call_monitor;
1007 std::list<media::Player::PlayerKey> paused_sessions;
1008 };
1009
1010-media::ServiceImplementation::ServiceImplementation(const Configuration& configuration) : d(new Private(configuration))
1011+media::ServiceImplementation::ServiceImplementation(const Configuration& configuration)
1012+ : d(new Private(configuration))
1013 {
1014 d->battery_observer->level().changed().connect([this](const media::power::Level& level)
1015 {
1016@@ -162,11 +168,12 @@
1017 {
1018 auto player = std::make_shared<media::PlayerImplementation>(media::PlayerImplementation::Configuration
1019 {
1020- conf.identity,
1021 conf.bus,
1022 conf.session,
1023 shared_from_this(),
1024 conf.key,
1025+ d->request_context_resolver,
1026+ d->request_authenticator,
1027 d->client_death_observer,
1028 d->power_state_controller
1029 });
1030
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
1036 #include "service_skeleton.h"
1037
1038-#include "apparmor.h"
1039-
1040 #include "mpris/media_player2.h"
1041 #include "mpris/metadata.h"
1042 #include "mpris/player.h"
1043@@ -55,7 +53,6 @@
1044 : impl(impl),
1045 object(impl->access_service()->add_object_for_path(
1046 dbus::traits::Service<media::Service>::object_path())),
1047- dbus_stub(impl->access_bus()),
1048 exported(impl->access_bus(), resolver)
1049 {
1050 object->install_method_handler<mpris::Service::CreateSession>(
1051@@ -99,19 +96,61 @@
1052 dbus::types::ObjectPath op{session_info.first};
1053 media::Player::PlayerKey key{session_info.second};
1054
1055- dbus_stub.get_connection_app_armor_security_async(msg->sender(), [this, msg, op, key](const std::string& profile)
1056- {
1057- media::Player::Configuration config
1058- {
1059- profile,
1060- key,
1061- impl->access_bus(),
1062- impl->access_service()->add_object_for_path(op)
1063- };
1064-
1065- try
1066- {
1067+ media::Player::Configuration config
1068+ {
1069+ key,
1070+ impl->access_bus(),
1071+ impl->access_service()->add_object_for_path(op)
1072+ };
1073+
1074+ try
1075+ {
1076+ auto session = impl->create_session(config);
1077+
1078+ bool inserted = false;
1079+ std::tie(std::ignore, inserted)
1080+ = session_store.insert(std::make_pair(key, session));
1081+
1082+ if (!inserted)
1083+ throw std::runtime_error("Problem persisting session in session store.");
1084+
1085+ auto reply = dbus::Message::make_method_return(msg);
1086+ reply->writer() << op;
1087+
1088+ impl->access_bus()->send(reply);
1089+ } catch(const std::runtime_error& e)
1090+ {
1091+ auto reply = dbus::Message::make_error(
1092+ msg,
1093+ mpris::Service::Errors::CreatingSession::name(),
1094+ e.what());
1095+ impl->access_bus()->send(reply);
1096+ }
1097+ }
1098+
1099+ void handle_create_fixed_session(const core::dbus::Message::Ptr& msg)
1100+ {
1101+ try
1102+ {
1103+ std::string name;
1104+ msg->reader() >> name;
1105+
1106+ if (fixed_session_store.count(name) == 0) {
1107+ // Create new session
1108+ auto session_info = create_session_info();
1109+
1110+ dbus::types::ObjectPath op{session_info.first};
1111+ media::Player::PlayerKey key{session_info.second};
1112+
1113+ media::Player::Configuration config
1114+ {
1115+ key,
1116+ impl->access_bus(),
1117+ impl->access_service()->add_object_for_path(op)
1118+ };
1119+
1120 auto session = impl->create_session(config);
1121+ session->lifetime().set(media::Player::Lifetime::resumable);
1122
1123 bool inserted = false;
1124 std::tie(std::ignore, inserted)
1125@@ -120,108 +159,20 @@
1126 if (!inserted)
1127 throw std::runtime_error("Problem persisting session in session store.");
1128
1129+ fixed_session_store.insert(std::make_pair(name, key));
1130
1131 auto reply = dbus::Message::make_method_return(msg);
1132 reply->writer() << op;
1133
1134 impl->access_bus()->send(reply);
1135- } catch(const std::runtime_error& e)
1136- {
1137- auto reply = dbus::Message::make_error(
1138- msg,
1139- mpris::Service::Errors::CreatingSession::name(),
1140- e.what());
1141- impl->access_bus()->send(reply);
1142- }
1143- });
1144- }
1145-
1146- void handle_create_fixed_session(const core::dbus::Message::Ptr& msg)
1147- {
1148- dbus_stub.get_connection_app_armor_security_async(msg->sender(), [this, msg](const std::string& profile)
1149- {
1150- try
1151- {
1152- std::string name;
1153- msg->reader() >> name;
1154-
1155- if (fixed_session_store.count(name) == 0) {
1156- // Create new session
1157- auto session_info = create_session_info();
1158-
1159- dbus::types::ObjectPath op{session_info.first};
1160- media::Player::PlayerKey key{session_info.second};
1161-
1162- media::Player::Configuration config
1163- {
1164- profile,
1165- key,
1166- impl->access_bus(),
1167- impl->access_service()->add_object_for_path(op)
1168- };
1169-
1170- auto session = impl->create_session(config);
1171- session->lifetime().set(media::Player::Lifetime::resumable);
1172-
1173- bool inserted = false;
1174- std::tie(std::ignore, inserted)
1175- = session_store.insert(std::make_pair(key, session));
1176-
1177- if (!inserted)
1178- throw std::runtime_error("Problem persisting session in session store.");
1179-
1180- fixed_session_store.insert(std::make_pair(name, key));
1181-
1182- auto reply = dbus::Message::make_method_return(msg);
1183- reply->writer() << op;
1184-
1185- impl->access_bus()->send(reply);
1186- }
1187- else {
1188- // Resume previous session
1189- auto key = fixed_session_store[name];
1190- if (session_store.count(key) == 0) {
1191- auto reply = dbus::Message::make_error(
1192- msg,
1193- mpris::Service::Errors::CreatingFixedSession::name(),
1194- "Unable to locate player session");
1195- impl->access_bus()->send(reply);
1196- return;
1197- }
1198-
1199- std::stringstream ss;
1200- ss << "/core/ubuntu/media/Service/sessions/" << key;
1201- dbus::types::ObjectPath op{ss.str()};
1202-
1203- auto reply = dbus::Message::make_method_return(msg);
1204- reply->writer() << op;
1205-
1206- impl->access_bus()->send(reply);
1207- }
1208- } catch(const std::runtime_error& e)
1209- {
1210- auto reply = dbus::Message::make_error(
1211- msg,
1212- mpris::Service::Errors::CreatingSession::name(),
1213- e.what());
1214- impl->access_bus()->send(reply);
1215- }
1216- });
1217- }
1218-
1219- void handle_resume_session(const core::dbus::Message::Ptr& msg)
1220- {
1221- dbus_stub.get_connection_app_armor_security_async(msg->sender(), [this, msg](const std::string&)
1222- {
1223- try
1224- {
1225- Player::PlayerKey key;
1226- msg->reader() >> key;
1227-
1228+ }
1229+ else {
1230+ // Resume previous session
1231+ auto key = fixed_session_store[name];
1232 if (session_store.count(key) == 0) {
1233 auto reply = dbus::Message::make_error(
1234 msg,
1235- mpris::Service::Errors::ResumingSession::name(),
1236+ mpris::Service::Errors::CreatingFixedSession::name(),
1237 "Unable to locate player session");
1238 impl->access_bus()->send(reply);
1239 return;
1240@@ -235,15 +186,49 @@
1241 reply->writer() << op;
1242
1243 impl->access_bus()->send(reply);
1244- } catch(const std::runtime_error& e)
1245- {
1246+ }
1247+ } catch(const std::runtime_error& e)
1248+ {
1249+ auto reply = dbus::Message::make_error(
1250+ msg,
1251+ mpris::Service::Errors::CreatingSession::name(),
1252+ e.what());
1253+ impl->access_bus()->send(reply);
1254+ }
1255+ }
1256+
1257+ void handle_resume_session(const core::dbus::Message::Ptr& msg)
1258+ {
1259+ try
1260+ {
1261+ Player::PlayerKey key;
1262+ msg->reader() >> key;
1263+
1264+ if (session_store.count(key) == 0) {
1265 auto reply = dbus::Message::make_error(
1266 msg,
1267- mpris::Service::Errors::CreatingSession::name(),
1268- e.what());
1269+ mpris::Service::Errors::ResumingSession::name(),
1270+ "Unable to locate player session");
1271 impl->access_bus()->send(reply);
1272+ return;
1273 }
1274- });
1275+
1276+ std::stringstream ss;
1277+ ss << "/core/ubuntu/media/Service/sessions/" << key;
1278+ dbus::types::ObjectPath op{ss.str()};
1279+
1280+ auto reply = dbus::Message::make_method_return(msg);
1281+ reply->writer() << op;
1282+
1283+ impl->access_bus()->send(reply);
1284+ } catch(const std::runtime_error& e)
1285+ {
1286+ auto reply = dbus::Message::make_error(
1287+ msg,
1288+ mpris::Service::Errors::CreatingSession::name(),
1289+ e.what());
1290+ impl->access_bus()->send(reply);
1291+ }
1292 }
1293
1294 void handle_pause_other_sessions(const core::dbus::Message::Ptr& msg)
1295@@ -260,8 +245,6 @@
1296 media::ServiceSkeleton* impl;
1297 dbus::Object::Ptr object;
1298
1299- // We query the apparmor profile to obtain an identity for players.
1300- org::freedesktop::dbus::DBus::Stub dbus_stub;
1301 // We track all running player instances.
1302 std::map<media::Player::PlayerKey, std::shared_ptr<media::Player>> session_store;
1303 std::map<std::string, media::Player::PlayerKey> fixed_session_store;

Subscribers

People subscribed via source and target branches

to all changes: