gitee.com/mysnapcore/mysnapd@v0.1.0/interfaces/builtin/cups_control.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016-2020 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  	"gitee.com/mysnapcore/mysnapd/interfaces"
    26  	"gitee.com/mysnapcore/mysnapd/interfaces/apparmor"
    27  	"gitee.com/mysnapcore/mysnapd/release"
    28  	"gitee.com/mysnapcore/mysnapd/snap"
    29  )
    30  
    31  // On classic systems where the slot is implicitly provided, the interface
    32  // allows access to the cups control socket.
    33  //
    34  // On systems where the slot is provided by an app snap, the cups-control
    35  // interface is the companion interface to the cups interface. The design of
    36  // these interfaces is based on the idea that the slot implementation (eg
    37  // cupsd) is expected to query snapd to determine if the cups-control interface
    38  // is connected or not for the peer client process and the print service will
    39  // mediate admin functionality (ie, the rules in these interfaces allow
    40  // connecting to the print service, but do not implement enforcement rules; it
    41  // is up to the print service to provide enforcement).
    42  const cupsControlSummary = `allows access to the CUPS control socket`
    43  
    44  // cups-control is implicit on classic but may also be provided by an app snap
    45  // on core or classic (the current design allows the snap provider to slots
    46  // both cups-control and cups or just cups-control (like with implicit classic
    47  // or any slot provider without mediation patches), but not just cups).
    48  const cupsControlBaseDeclarationSlots = `
    49    cups-control:
    50      allow-installation:
    51        slot-snap-type:
    52          - app
    53          - core
    54      deny-auto-connection: true
    55      deny-connection:
    56        on-classic: false
    57  `
    58  
    59  const cupsControlPermanentSlotAppArmor = `
    60  # Allow daemon access to create the CUPS socket
    61  /{,var/}run/cups/ rw,
    62  /{,var/}run/cups/** rwk,
    63  
    64  # Allow cups to verify passwords directly
    65  /etc/shadow r,
    66  /var/lib/extrausers/shadow r,
    67  
    68  # Some versions of CUPS will verify the connecting pid's
    69  # security label
    70  @{PROC}/[0-9]*/attr/{,apparmor/}current r,
    71  
    72  # Allow daemon access to the color manager on the system
    73  dbus (receive, send)
    74      bus=system
    75      path=/org/freedesktop/ColorManager
    76      interface=org.freedesktop.ColorManager
    77      peer=(name=org.freedesktop.ColorManager),
    78  
    79  # Allow daemon to send notifications
    80  dbus (send)
    81      bus=system
    82      path=/org/cups/cupsd/Notifier
    83      interface=org.cups.cupsd.Notifier
    84      peer=(label=unconfined),
    85  
    86  # Allow daemon to send signals to its snap_daemon processes
    87  capability kill,
    88  
    89  # Allow daemon to manage snap_daemon files and directories
    90  capability fsetid,
    91  `
    92  
    93  const cupsControlConnectedSlotAppArmor = `
    94  # Allow daemon to send notifications to connected snaps
    95  dbus (send)
    96      bus=system
    97      path=/org/cups/cupsd/Notifier
    98      interface=org.cups.cupsd.Notifier
    99      peer=(label=###PLUG_SECURITY_TAGS###),
   100  `
   101  
   102  const cupsControlConnectedPlugAppArmor = `
   103  # Allow communicating with the cups server for printing and configuration.
   104  
   105  #include <abstractions/cups-client>
   106  /{,var/}run/cups/printcap r,
   107  
   108  # Allow receiving all DBus signal notifications from the daemon (see
   109  # notifier/dbus.c in cups sources)
   110  dbus (receive)
   111      bus=system
   112      path=/org/cups/cupsd/Notifier
   113      interface=org.cups.cupsd.Notifier
   114      peer=(label=###SLOT_SECURITY_TAGS###),
   115  `
   116  
   117  type cupsControlInterface struct {
   118  	commonInterface
   119  }
   120  
   121  func (iface *cupsControlInterface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error {
   122  	// On classic, only apply slot snippet when running as application snap
   123  	// on classic since the slot side may be from the classic OS or snap.
   124  	if !implicitSystemPermanentSlot(slot) {
   125  		spec.AddSnippet(cupsControlPermanentSlotAppArmor)
   126  	}
   127  	return nil
   128  }
   129  
   130  func (iface *cupsControlInterface) AppArmorConnectedSlot(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   131  	// On classic, only apply slot snippet when running as application snap
   132  	// on classic since the slot side may be from the classic OS or snap.
   133  	if !implicitSystemConnectedSlot(slot) {
   134  		old := "###PLUG_SECURITY_TAGS###"
   135  		new := plugAppLabelExpr(plug)
   136  		snippet := strings.Replace(cupsControlConnectedSlotAppArmor, old, new, -1)
   137  		spec.AddSnippet(snippet)
   138  	}
   139  	return nil
   140  }
   141  
   142  func (iface *cupsControlInterface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error {
   143  	old := "###SLOT_SECURITY_TAGS###"
   144  	var new string
   145  	// If we're running on classic, cups may be installed either as a snap
   146  	// or as part of the classic OS. If it is part of the classic OS, it
   147  	// will not have a security label like it would when installed as a
   148  	// snap.
   149  	if implicitSystemConnectedSlot(slot) {
   150  		// cupsd from the OS may be confined or unconfined. Newer
   151  		// releases may use the 'cupsd' label instead of the old
   152  		// path-based label.
   153  		new = "\"{unconfined,/usr/sbin/cupsd,cupsd}\""
   154  	} else {
   155  		new = slotAppLabelExpr(slot)
   156  	}
   157  
   158  	// implement 'implicitOnCore: false/implicitOnClassic: true' by only
   159  	// applying the snippet if the slot is an app or we are on classic
   160  	if slot.Snap().Type() == snap.TypeApp || release.OnClassic {
   161  		snippet := strings.Replace(cupsControlConnectedPlugAppArmor, old, new, -1)
   162  		spec.AddSnippet(snippet)
   163  	}
   164  	return nil
   165  }
   166  
   167  func init() {
   168  	registerIface(&cupsControlInterface{
   169  		commonInterface: commonInterface{
   170  			name:                 "cups-control",
   171  			summary:              cupsControlSummary,
   172  			baseDeclarationSlots: cupsControlBaseDeclarationSlots,
   173  			implicitOnCore:       false,
   174  			implicitOnClassic:    true,
   175  		},
   176  	})
   177  }