29 namespace ubuntu = apparmor::ubuntu;
36 std::string authority;
44 Uri parse_uri(
const std::string& s)
49 const std::size_t scheme{2};
50 const std::size_t authority{4};
51 const std::size_t path{5};
52 const std::size_t query{7};
53 const std::size_t fragment{9};
56 static const std::regex regex{R
"delim(^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)delim"}; 59 if (not std::regex_match(s, match, regex))
throw std::runtime_error
61 "Not a valid URI: " + s
66 match.str(index.scheme),
67 match.str(index.authority),
68 match.str(index.path),
69 match.str(index.query),
70 match.str(index.fragment)
74 static constexpr std::size_t index_package{1};
75 static constexpr std::size_t index_app{2};
76 static const std::string unity_name{
"unity8-dash"};
77 static const std::string unity8_snap_name{
"snap.unity8-session.unity8-session"};
81 static const std::string mediaplayer_snap_name{
"snap.mediaplayer-app.mediaplayer-app"};
82 static const std::string music_snap_name{
"snap.music-app.music-app"};
85 bool process_context_name(
const std::string& s, std::smatch& out,
86 std::string& pkg_name)
89 static const std::regex short_re{
"(.*)_(.*)"};
90 static const std::regex full_re{
"(.*)_(.*)_(.*)"};
91 static const std::regex trust_store_re{
"(.*)-(.*)"};
93 if ((s ==
"messaging-app" or s == unity_name or s == unity8_snap_name or
94 s == mediaplayer_snap_name or s == music_snap_name)
95 and std::regex_match(s, out, trust_store_re))
101 if (std::regex_match(s, out, full_re) or std::regex_match(s, out, short_re))
103 pkg_name = out[index_package];
111 apparmor::ubuntu::Context::Context(
const std::string& name)
113 unconfined_{
str() == ubuntu::unconfined},
114 unity_{name == unity_name || name == unity8_snap_name},
115 has_package_name_{process_context_name(
str(), match_, pkg_name_)}
117 MH_DEBUG(
"apparmor profile name: %s", name);
121 throw std::logic_error
123 "apparmor::ubuntu::Context: Invalid profile name " +
str()
139 return has_package_name_;
149 return std::string{match_[index_package]} +
"-" + std::string{match_[index_app]};
157 const std::string& name,
169 return Result{
true,
"Client allowed access since it's unconfined"};
171 Uri parsed_uri = parse_uri(uri);
174 MH_DEBUG(
"parsed_uri.path: %s", parsed_uri.path);
177 if (parsed_uri.path.find(std::string(
".local/share/" + context.
package_name() +
"/")) != std::string::npos ||
178 parsed_uri.path.find(std::string(
".cache/" + context.
package_name() +
"/")) != std::string::npos)
189 (parsed_uri.path.find(std::string(
".local/share/com.ubuntu." + context.
profile_name() +
"/")) != std::string::npos ||
190 parsed_uri.path.find(std::string(
".cache/com.ubuntu." + context.
profile_name() +
"/")) != std::string::npos))
198 else if (parsed_uri.path.find(std::string(
"opt/click.ubuntu.com/")) != std::string::npos &&
199 parsed_uri.path.find(context.
package_name()) != std::string::npos)
201 return Result{
true,
"Client can access content in own opt directory"};
203 else if ((parsed_uri.path.find(std::string(
"/system/media/audio/ui/")) != std::string::npos ||
204 parsed_uri.path.find(std::string(
"/android/system/media/audio/ui/")) != std::string::npos) &&
207 return Result{
true,
"Camera app can access ui sounds"};
218 (parsed_uri.path.find(std::string(
"Music/")) != std::string::npos ||
219 parsed_uri.path.find(std::string(
"Videos/")) != std::string::npos ||
220 parsed_uri.path.find(std::string(
"/media")) != std::string::npos))
222 return Result{
true,
"Client can access content in ~/Music or ~/Videos"};
224 else if (parsed_uri.path.find(std::string(
"/usr/share/sounds")) != std::string::npos)
226 return Result{
true,
"Client can access content in /usr/share/sounds"};
228 else if (parsed_uri.scheme ==
"http" ||
229 parsed_uri.scheme ==
"https" ||
230 parsed_uri.scheme ==
"rtsp")
232 return Result{
true,
"Client can access streaming content"};
235 return Result{
false,
"Client is not allowed to access: " + uri};
241 return std::make_shared<apparmor::ubuntu::DBusDaemonRequestContextResolver>(es.
session);
247 return std::make_shared<apparmor::ubuntu::ExistingAuthenticator>();
DBusDaemonRequestContextResolver(const core::dbus::Bus::Ptr &)
const std::string & str() const
std::shared_ptr< RequestContextResolver > Ptr
virtual bool has_package_name() const
void resolve_context_for_dbus_name_async(const std::string &name, ResolveCallback) override
virtual bool is_unity() const
void get_connection_app_armor_security_async(const std::string &name, std::function< void(const std::string &)> handler)
std::function< void(const Context &)> ResolveCallback
virtual std::string package_name() const
virtual bool is_unconfined() const
virtual std::string profile_name() const