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

Proposed by Ricardo Salveti
Status: Merged
Approved by: Ricardo Mendoza
Approved revision: 122
Merged at revision: 123
Proposed branch: lp:~phablet-team/media-hub/introduce-apparmor-interfaces
Merge into: lp:media-hub
Prerequisite: lp:~phablet-team/media-hub/introduce-call-monitor-interface
Diff against target: 1302 lines (+685/-313)
15 files modified
src/core/media/CMakeLists.txt (+3/-0)
src/core/media/apparmor.h (+0/-93)
src/core/media/apparmor/context.cpp (+34/-0)
src/core/media/apparmor/context.h (+51/-0)
src/core/media/apparmor/dbus.h (+94/-0)
src/core/media/apparmor/ubuntu.cpp (+198/-0)
src/core/media/apparmor/ubuntu.h (+167/-0)
src/core/media/player.cpp (+0/-1)
src/core/media/player_configuration.h (+0/-3)
src/core/media/player_implementation.cpp (+2/-1)
src/core/media/player_implementation.h (+3/-1)
src/core/media/player_skeleton.cpp (+16/-93)
src/core/media/player_skeleton.h (+9/-3)
src/core/media/service_implementation.cpp (+9/-2)
src/core/media/service_skeleton.cpp (+99/-116)
To merge this branch: bzr merge lp:~phablet-team/media-hub/introduce-apparmor-interfaces
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing
Jim Hodapp code Pending
Review via email: mp+251807@code.launchpad.net

This proposal supersedes a proposal from 2015-03-04.

Commit message

Add an interface apparmor::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 : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
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

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

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

Subscribers

People subscribed via source and target branches

to all changes: