github.com/rigado/snapd@v2.42.5-go-mod+incompatible/interfaces/builtin/avahi_observe.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package builtin
    21  
    22  import (
    23  	"strings"
    24  
    25  	"github.com/snapcore/snapd/interfaces"
    26  	"github.com/snapcore/snapd/interfaces/apparmor"
    27  	"github.com/snapcore/snapd/interfaces/dbus"
    28  	"github.com/snapcore/snapd/snap"
    29  )
    30  
    31  const avahiObserveSummary = `allows discovery on a local network via the mDNS/DNS-SD protocol suite`
    32  
    33  const avahiObserveBaseDeclarationSlots = `
    34    avahi-observe:
    35      allow-installation:
    36        slot-snap-type:
    37          - app
    38          - core
    39      deny-auto-connection: true
    40      deny-connection:
    41        on-classic: false
    42  `
    43  
    44  const avahiObservePermanentSlotAppArmor = `
    45  network netlink,
    46  
    47  # Allow access to daemon to create socket
    48  /{,var/}run/avahi-daemon/  w,
    49  /{,var/}run/avahi-daemon/{pid,socket} rwk,
    50  
    51  # Description: Allow operating as the avahi service. This gives
    52  # privileged access to the system.
    53  #include <abstractions/dbus-strict>
    54  
    55  dbus (send)
    56      bus=system
    57      path=/org/freedesktop/DBus
    58      interface=org.freedesktop.DBus
    59      member={Request,Release}Name
    60      peer=(name=org.freedesktop.DBus, label=unconfined),
    61  
    62  dbus (receive, send)
    63      bus=system
    64      path=/org/freedesktop/DBus
    65      interface=org.freedesktop.DBus
    66      member=GetConnectionUnixProcessID
    67      peer=(label=unconfined),
    68  
    69  dbus (receive, send)
    70      bus=system
    71      path=/org/freedesktop/DBus
    72      interface=org.freedesktop.DBus
    73      member=GetConnectionUnixUser
    74      peer=(label=unconfined),
    75  
    76  # Allow binding the service to the requested connection name
    77  dbus (bind)
    78      bus=system
    79      name="org.freedesktop.Avahi",
    80  
    81  # Allow traffic to/from our path and interface with any method for unconfined
    82  # clients to talk to our service.
    83  dbus (receive, send)
    84     bus=system
    85     path=/org/freedesktop/Avahi{,/**}
    86     interface=org.freedesktop.Avahi*
    87     peer=(label=unconfined),
    88  
    89  # Allow traffic to/from org.freedesktop.DBus for Avahi service
    90  dbus (receive, send)
    91     bus=system
    92     path=/org/freedesktop/Avahi{,/**}
    93     interface=org.freedesktop.DBus.*
    94     peer=(label=unconfined),
    95  `
    96  
    97  // Note: avahiObserveConnectedSlotAppArmor is also used by avahi-control in AppArmorConnectedSlot
    98  const avahiObserveConnectedSlotAppArmor = `
    99  # Description: Allow operating as the avahi service. This gives
   100  # privileged access to the system.
   101  #include <abstractions/dbus-strict>
   102  
   103  # Allow all access to Avahi service
   104  
   105  dbus (receive)
   106      bus=system
   107      path=/
   108      interface=org.freedesktop.DBus.Peer
   109      member=Ping
   110      peer=(label=###PLUG_SECURITY_TAGS###),
   111  
   112  dbus (receive)
   113      bus=system
   114      path=/
   115      interface=org.freedesktop.Avahi.Server
   116      peer=(label=###PLUG_SECURITY_TAGS###),
   117  
   118  dbus (send)
   119      bus=system
   120      interface=org.freedesktop.Avahi.Server
   121      member=StateChanged
   122      peer=(label=###PLUG_SECURITY_TAGS###),
   123  
   124  # address resolving
   125  dbus (receive)
   126      bus=system
   127      path=/Client*/AddressResolver*
   128      interface=org.freedesktop.Avahi.AddressResolver
   129      peer=(label=###PLUG_SECURITY_TAGS###),
   130  
   131  dbus (send)
   132      bus=system
   133      interface=org.freedesktop.Avahi.AddressResolver
   134      peer=(name=org.freedesktop.Avahi, label=###PLUG_SECURITY_TAGS###),
   135  
   136  # host name resolving
   137  dbus (receive)
   138      bus=system
   139      path=/Client*/HostNameResolver*
   140      interface=org.freedesktop.Avahi.HostNameResolver
   141      peer=(label=###PLUG_SECURITY_TAGS###),
   142  
   143  dbus (send)
   144      bus=system
   145      interface=org.freedesktop.Avahi.HostNameResolver
   146      peer=(label=###PLUG_SECURITY_TAGS###),
   147  
   148  # service resolving
   149  dbus (receive)
   150      bus=system
   151      path=/Client*/ServiceResolver*
   152      interface=org.freedesktop.Avahi.ServiceResolver
   153      peer=(label=###PLUG_SECURITY_TAGS###),
   154  
   155  dbus (send)
   156      bus=system
   157      interface=org.freedesktop.Avahi.ServiceResolver
   158      peer=(label=###PLUG_SECURITY_TAGS###),
   159  
   160  # domain browsing
   161  dbus (receive)
   162      bus=system
   163      path=/Client*/DomainBrowser*
   164      interface=org.freedesktop.Avahi.DomainBrowser
   165      peer=(label=###PLUG_SECURITY_TAGS###),
   166  
   167  dbus (send)
   168      bus=system
   169      interface=org.freedesktop.Avahi.DomainBrowser
   170      peer=(label=###PLUG_SECURITY_TAGS###),
   171  
   172  # record browsing
   173  dbus (receive)
   174      bus=system
   175      path=/Client*/RecordBrowser*
   176      interface=org.freedesktop.Avahi.RecordBrowser
   177      peer=(label=###PLUG_SECURITY_TAGS###),
   178  
   179  dbus (send)
   180      bus=system
   181      interface=org.freedesktop.Avahi.RecordBrowser
   182      peer=(label=###PLUG_SECURITY_TAGS###),
   183  
   184  # service browsing
   185  dbus (receive)
   186      bus=system
   187      path=/Client*/ServiceBrowser*
   188      interface=org.freedesktop.Avahi.ServiceBrowser
   189      peer=(label=###PLUG_SECURITY_TAGS###),
   190  
   191  dbus (send)
   192      bus=system
   193      interface=org.freedesktop.Avahi.ServiceBrowser
   194      peer=(label=###PLUG_SECURITY_TAGS###),
   195  
   196  # service type browsing
   197  dbus (receive)
   198      bus=system
   199      path=/Client*/ServiceTypeBrowser*
   200      interface=org.freedesktop.Avahi.ServiceTypeBrowser
   201      peer=(label=###PLUG_SECURITY_TAGS###),
   202  
   203  dbus (send)
   204      bus=system
   205      interface=org.freedesktop.Avahi.ServiceTypeBrowser
   206      peer=(label=###PLUG_SECURITY_TAGS###),
   207  `
   208  
   209  // Note: avahiObservePermanentSlotDBus is used by avahi-control in DBusPermanentSlot
   210  const avahiObservePermanentSlotDBus = `
   211  <!-- Only root can own the Avahi service -->
   212  <policy user="root">
   213    <allow own="org.freedesktop.Avahi"/>
   214  </policy>
   215  
   216  <!-- Allow anyone to invoke methods on Avahi server, except SetHostName -->
   217  <policy context="default">
   218    <allow send_destination="org.freedesktop.Avahi"/>
   219    <allow receive_sender="org.freedesktop.Avahi"/>
   220  
   221    <deny send_destination="org.freedesktop.Avahi"
   222          send_interface="org.freedesktop.Avahi.Server" send_member="SetHostName"/>
   223  </policy>
   224  
   225  <!-- bus policy for "netdev" group is removed as it does not apply to Ubuntu core -->
   226  <!-- Allow root to set  SetHostName -->
   227  <policy user="root">
   228    <allow send_destination="org.freedesktop.Avahi"/>
   229    <allow receive_sender="org.freedesktop.Avahi"/>
   230  </policy>
   231  `
   232  
   233  // Note: avahiObserveConnectedPlugAppArmor is also used by avahi-control in AppArmorConnectedPlug
   234  const avahiObserveConnectedPlugAppArmor = `
   235  # Description: allows domain, record, service, and service type browsing
   236  # as well as address, host and service resolving
   237  
   238  /{,var/}run/avahi-daemon/socket rw,
   239  
   240  #include <abstractions/dbus-strict>
   241  dbus (send)
   242      bus=system
   243      path=/
   244      interface=org.freedesktop.DBus.Peer
   245      member=Ping
   246      peer=(name=org.freedesktop.Avahi,label=###SLOT_SECURITY_TAGS###),
   247  
   248  # Allow accessing DBus properties and resolving
   249  dbus (send)
   250      bus=system
   251      path=/
   252      interface=org.freedesktop.Avahi.Server
   253      member={Get*,Resolve*,IsNSSSupportAvailable}
   254      peer=(name=org.freedesktop.Avahi,label=###SLOT_SECURITY_TAGS###),
   255  
   256  # Allow receiving anything from the slot server
   257  dbus (receive)
   258      bus=system
   259      interface=org.freedesktop.Avahi.Server
   260      peer=(label=###SLOT_SECURITY_TAGS###),
   261  
   262  # Don't allow introspection since it reveals too much (path is not service
   263  # specific for unconfined)
   264  # do not use peer=(label=unconfined) here since this is DBus activated
   265  #dbus (send)
   266  #    bus=system
   267  #    path=/
   268  #    interface=org.freedesktop.DBus.Introspectable
   269  #    member=Introspect,
   270  
   271  # These allows tampering with other snap's browsers, so don't autoconnect for
   272  # now.
   273  
   274  # address resolving
   275  dbus (send)
   276      bus=system
   277      path=/
   278      interface=org.freedesktop.Avahi.Server
   279      member=AddressResolverNew
   280      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   281  
   282  dbus (send)
   283      bus=system
   284      path=/Client*/AddressResolver*
   285      interface=org.freedesktop.Avahi.AddressResolver
   286      member=Free
   287      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   288  
   289  dbus (receive)
   290      bus=system
   291      interface=org.freedesktop.Avahi.AddressResolver
   292      peer=(label=###SLOT_SECURITY_TAGS###),
   293  
   294  # host name resolving
   295  dbus (send)
   296      bus=system
   297      path=/
   298      interface=org.freedesktop.Avahi.Server
   299      member=HostNameResolverNew
   300      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   301  
   302  dbus (send)
   303      bus=system
   304      path=/Client*/HostNameResolver*
   305      interface=org.freedesktop.Avahi.HostNameResolver
   306      member=Free
   307      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   308  
   309  dbus (receive)
   310      bus=system
   311      interface=org.freedesktop.Avahi.HostNameResolver
   312      peer=(label=###SLOT_SECURITY_TAGS###),
   313  
   314  # service resolving
   315  dbus (send)
   316      bus=system
   317      path=/
   318      interface=org.freedesktop.Avahi.Server
   319      member=ServiceResolverNew
   320      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   321  
   322  dbus (send)
   323      bus=system
   324      path=/Client*/ServiceResolver*
   325      interface=org.freedesktop.Avahi.ServiceResolver
   326      member=Free
   327      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   328  
   329  dbus (receive)
   330      bus=system
   331      interface=org.freedesktop.Avahi.ServiceResolver
   332      peer=(label=###SLOT_SECURITY_TAGS###),
   333  
   334  # domain browsing
   335  dbus (send)
   336      bus=system
   337      path=/
   338      interface=org.freedesktop.Avahi.Server
   339      member=DomainBrowserNew
   340      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   341  
   342  dbus (send)
   343      bus=system
   344      path=/Client*/DomainBrowser*
   345      interface=org.freedesktop.Avahi.DomainBrowser
   346      member=Free
   347      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   348  
   349  dbus (receive)
   350      bus=system
   351      interface=org.freedesktop.Avahi.DomainBrowser
   352      peer=(label=###SLOT_SECURITY_TAGS###),
   353  
   354  # record browsing
   355  dbus (send)
   356      bus=system
   357      path=/
   358      interface=org.freedesktop.Avahi.Server
   359      member=RecordBrowserNew
   360      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   361  
   362  dbus (send)
   363      bus=system
   364      path=/Client*/RecordBrowser*
   365      interface=org.freedesktop.Avahi.RecordBrowser
   366      member=Free
   367      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   368  
   369  dbus (receive)
   370      bus=system
   371      interface=org.freedesktop.Avahi.RecordBrowser
   372      peer=(label=###SLOT_SECURITY_TAGS###),
   373  
   374  # service browsing
   375  dbus (send)
   376      bus=system
   377      path=/
   378      interface=org.freedesktop.Avahi.Server
   379      member=ServiceBrowserNew
   380      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   381  
   382  dbus (send)
   383      bus=system
   384      path=/Client*/ServiceBrowser*
   385      interface=org.freedesktop.Avahi.ServiceBrowser
   386      member=Free
   387      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   388  
   389  dbus (receive)
   390      bus=system
   391      interface=org.freedesktop.Avahi.ServiceBrowser
   392      peer=(label=###SLOT_SECURITY_TAGS###),
   393  
   394  # Service type browsing
   395  dbus (send)
   396      bus=system
   397      path=/
   398      interface=org.freedesktop.Avahi.Server
   399      member=ServiceTypeBrowserNew
   400      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   401  
   402  dbus (send)
   403      bus=system
   404      path=/Client*/ServiceTypeBrowser*
   405      interface=org.freedesktop.Avahi.ServiceTypeBrowser
   406      member=Free
   407      peer=(name=org.freedesktop.Avahi, label=###SLOT_SECURITY_TAGS###),
   408  
   409  dbus (receive)
   410      bus=system
   411      interface=org.freedesktop.Avahi.ServiceTypeBrowser
   412      peer=(label=###SLOT_SECURITY_TAGS###),
   413  `
   414  
   415  type avahiObserveInterface struct{}
   416  
   417  func (iface *avahiObserveInterface) Name() string {
   418  	return "avahi-observe"
   419  }
   420  
   421  func (iface *avahiObserveInterface) StaticInfo() interfaces.StaticInfo {
   422  	return interfaces.StaticInfo{
   423  		Summary:              avahiObserveSummary,
   424  		ImplicitOnClassic:    true,
   425  		BaseDeclarationSlots: avahiObserveBaseDeclarationSlots,
   426  	}
   427  }
   428  
   429  func (iface *avahiObserveInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   430  	old := "###SLOT_SECURITY_TAGS###"
   431  	var new string
   432  	// If we're running on classic, Avahi may be installed either as a snap of
   433  	// as part of the OS. If it is part of the OS, it will not have a security
   434  	// label like it would when installed as a snap.
   435  	if implicitSystemConnectedSlot(slot) {
   436  		// avahi from the OS is typically unconfined but known to sometimes be confined
   437  		new = "\"{unconfined,/usr/sbin/avahi-daemon}\""
   438  	} else {
   439  		new = slotAppLabelExpr(slot)
   440  	}
   441  	snippet := strings.Replace(avahiObserveConnectedPlugAppArmor, old, new, -1)
   442  	spec.AddSnippet(snippet)
   443  	return nil
   444  }
   445  
   446  func (iface *avahiObserveInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error {
   447  	// Only apply slot snippet when running as application snap
   448  	// on classic, slot side can be system or application
   449  	if !implicitSystemPermanentSlot(slot) {
   450  		spec.AddSnippet(avahiObservePermanentSlotAppArmor)
   451  	}
   452  	return nil
   453  }
   454  
   455  func (iface *avahiObserveInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   456  	// Only apply slot snippet when running as application snap
   457  	// on classic, slot side can be system or application
   458  	if !implicitSystemConnectedSlot(slot) {
   459  		old := "###PLUG_SECURITY_TAGS###"
   460  		new := plugAppLabelExpr(plug)
   461  		snippet := strings.Replace(avahiObserveConnectedSlotAppArmor, old, new, -1)
   462  		spec.AddSnippet(snippet)
   463  	}
   464  	return nil
   465  }
   466  
   467  func (iface *avahiObserveInterface) DBusPermanentSlot(spec *dbus.Specification, slot *snap.SlotInfo) error {
   468  	// Only apply slot snippet when running as application snap
   469  	// on classic, slot side can be system or application
   470  	if !implicitSystemPermanentSlot(slot) {
   471  		spec.AddSnippet(avahiObservePermanentSlotDBus)
   472  	}
   473  	return nil
   474  }
   475  
   476  func (iface *avahiObserveInterface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool {
   477  	// allow what declarations allowed
   478  	return true
   479  }
   480  
   481  func init() {
   482  	registerIface(&avahiObserveInterface{})
   483  }