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 }