30 namespace ubuntu = apparmor::ubuntu;
37 std::string authority;
45 Uri parse_uri(
const std::string& s)
50 const std::size_t scheme{2};
51 const std::size_t authority{4};
52 const std::size_t path{5};
53 const std::size_t query{7};
54 const std::size_t fragment{9};
57 static const std::regex regex{R
"delim(^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)delim"}; 60 if (not std::regex_match(s, match, regex))
throw std::runtime_error
62 "Not a valid URI: " + s
67 match.str(index.scheme),
68 match.str(index.authority),
69 match.str(index.path),
70 match.str(index.query),
71 match.str(index.fragment)
75 static constexpr std::size_t index_package{1};
76 static constexpr std::size_t index_app{2};
77 static const std::string unity_name{
"unity8-dash"};
78 static const std::string unity8_snap_name{
"snap.unity8-session.unity8-session"};
82 static const std::string mediaplayer_snap_name{
"snap.mediaplayer-app.mediaplayer-app"};
83 static const std::string music_snap_name{
"snap.music-app.music-app"};
86 bool process_context_name(
const std::string& s, std::smatch& out,
87 std::string& pkg_name)
90 static const std::regex short_re{
"(.*)_(.*)"};
91 static const std::regex full_re{
"(.*)_(.*)_(.*)"};
92 static const std::regex trust_store_re{
"(.*)-(.*)"};
94 if ((s ==
"messaging-app" or s == unity_name or s == unity8_snap_name or
95 s == mediaplayer_snap_name or s == music_snap_name)
96 and std::regex_match(s, out, trust_store_re))
102 if (std::regex_match(s, out, full_re) or std::regex_match(s, out, short_re))
104 pkg_name = out[index_package];
112 apparmor::ubuntu::Context::Context(
const std::string& name)
114 unconfined_{
str() == ubuntu::unconfined},
115 unity_{name == unity_name || name == unity8_snap_name},
116 has_package_name_{process_context_name(
str(), match_, pkg_name_)}
118 MH_DEBUG(
"apparmor profile name: %s", name);
122 throw std::logic_error
124 "apparmor::ubuntu::Context: Invalid profile name " +
str()
140 return has_package_name_;
150 return std::string{match_[index_package]} +
"-" + std::string{match_[index_app]};
158 const std::string& name,
170 return Result{
true,
"Client allowed access since it's unconfined"};
172 Uri parsed_uri = parse_uri(uri);
175 MH_DEBUG(
"parsed_uri.path: %s", parsed_uri.path);
178 if (parsed_uri.path.find(std::string(
".local/share/" + context.
package_name() +
"/")) != std::string::npos ||
179 parsed_uri.path.find(std::string(
".cache/" + context.
package_name() +
"/")) != std::string::npos ||
180 parsed_uri.path.find(std::string(
"/run/user/" + std::to_string(geteuid()) +
"/confined/" + context.
package_name())) != std::string::npos)
191 (parsed_uri.path.find(std::string(
".local/share/com.ubuntu." + context.
profile_name() +
"/")) != std::string::npos ||
192 parsed_uri.path.find(std::string(
".cache/com.ubuntu." + context.
profile_name() +
"/")) != std::string::npos))
200 else if (parsed_uri.path.find(std::string(
"opt/click.ubuntu.com/")) != std::string::npos &&
201 parsed_uri.path.find(context.
package_name()) != std::string::npos)
203 return Result{
true,
"Client can access content in own opt directory"};
205 else if ((parsed_uri.path.find(std::string(
"/system/media/audio/ui/")) != std::string::npos ||
206 parsed_uri.path.find(std::string(
"/android/system/media/audio/ui/")) != std::string::npos) &&
209 return Result{
true,
"Camera app can access ui sounds"};
220 (parsed_uri.path.find(std::string(
"Music/")) != std::string::npos ||
221 parsed_uri.path.find(std::string(
"Videos/")) != std::string::npos ||
222 parsed_uri.path.find(std::string(
"/media")) != std::string::npos))
224 return Result{
true,
"Client can access content in ~/Music or ~/Videos"};
226 else if (parsed_uri.path.find(std::string(
"/usr/share/sounds")) != std::string::npos)
228 return Result{
true,
"Client can access content in /usr/share/sounds"};
230 else if (parsed_uri.scheme ==
"http" ||
231 parsed_uri.scheme ==
"https" ||
232 parsed_uri.scheme ==
"rtsp")
234 return Result{
true,
"Client can access streaming content"};
237 return Result{
false,
"Client is not allowed to access: " + uri};
243 return std::make_shared<apparmor::ubuntu::DBusDaemonRequestContextResolver>(es.
session);
249 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