gitee.com/mysnapcore/mysnapd@v0.1.0/interfaces/builtin/pkcs11.go (about) 1 // -*- Mode: Go; indent-tabs-mode: t -*- 2 3 /* 4 * Copyright (C) 2016-2017 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 "fmt" 24 "path/filepath" 25 26 "gitee.com/mysnapcore/mysnapd/interfaces" 27 "gitee.com/mysnapcore/mysnapd/interfaces/apparmor" 28 "gitee.com/mysnapcore/mysnapd/interfaces/seccomp" 29 apparmor_sandbox "gitee.com/mysnapcore/mysnapd/sandbox/apparmor" 30 "gitee.com/mysnapcore/mysnapd/snap" 31 ) 32 33 const pkcs11Summary = `allows use of pkcs11 framework and access to exposed tokens` 34 35 const pkcs11BaseDeclarationSlots = ` 36 pkcs11: 37 allow-installation: false 38 deny-auto-connection: true 39 ` 40 41 type pkcs11Interface struct{} 42 43 // Name of the pkcs11 interface. 44 func (iface *pkcs11Interface) Name() string { 45 return "pkcs11" 46 } 47 48 func (iface *pkcs11Interface) StaticInfo() interfaces.StaticInfo { 49 return interfaces.StaticInfo{ 50 Summary: pkcs11Summary, 51 BaseDeclarationSlots: pkcs11BaseDeclarationSlots, 52 } 53 } 54 55 func (iface *pkcs11Interface) String() string { 56 return iface.Name() 57 } 58 59 const pkcs11PermanentSlotSecComp = ` 60 # Description: Allow operating as an p11-kit server. This gives privileged access 61 # to the system. 62 # Needed for server launch 63 bind 64 listen 65 66 # Needed by server upon client connect 67 accept 68 accept4 69 ` 70 71 func (iface *pkcs11Interface) getSocketPath(slot *snap.SlotInfo) (string, error) { 72 socketAttr, isSet := slot.Attrs["pkcs11-socket"] 73 if !isSet { 74 return "", fmt.Errorf(`cannot use pkcs11 slot without "pkcs11-socket" attribute`) 75 } 76 77 socketPath, ok := socketAttr.(string) 78 if !ok { 79 return "", fmt.Errorf(`pkcs11 slot "pkcs11-socket" attribute must be a string, not %v`, 80 socketAttr) 81 } 82 83 if ok := cleanSubPath(socketPath); !ok { 84 return "", fmt.Errorf("pkcs11 unix socket path is not clean: %q", socketPath) 85 } 86 87 // separate socket name and check socket is in /run/p11-kit 88 if filepath.Dir(socketPath) != "/run/p11-kit" { 89 return "", fmt.Errorf("pkcs11 unix socket has to be in the /run/p11-kit directory: %q", socketPath) 90 } 91 92 return socketPath, nil 93 } 94 95 func (iface *pkcs11Interface) BeforePrepareSlot(slot *snap.SlotInfo) error { 96 socketPath, err := iface.getSocketPath(slot) 97 if err != nil { 98 return err 99 } 100 101 if err := apparmor_sandbox.ValidateNoAppArmorRegexp(socketPath); err != nil { 102 return fmt.Errorf("pkcs11 unix socket path is invalid: %v", err) 103 } 104 return err 105 } 106 107 func (iface *pkcs11Interface) SecCompPermanentSlot(spec *seccomp.Specification, slot *snap.SlotInfo) error { 108 spec.AddSnippet(pkcs11PermanentSlotSecComp) 109 return nil 110 } 111 112 func (iface *pkcs11Interface) AppArmorConnectedPlug(spec *apparmor.Specification, plug *interfaces.ConnectedPlug, slot *interfaces.ConnectedSlot) error { 113 var socketPath string 114 if err := slot.Attr("pkcs11-socket", &socketPath); err != nil || socketPath == "" { 115 return fmt.Errorf(`internal error: pkcs11 slot %q must have a unix socket "pkcs11-socket" attribute`, slot.Ref()) 116 } 117 118 // The validation from BeforePrepareSlot() ensures that the socket path starts with "/run/p11-kit" 119 socketRule := fmt.Sprintf(`"/{,var/}%s" rw,`, socketPath[1:]) 120 // pkcs11 server unix socket 121 spec.AddSnippet(fmt.Sprintf(`# pkcs11 socket 122 %s 123 # pkcs11 config for p11-proxy 124 /etc/pkcs11/{,**} r, 125 # pkcs11 tools 126 /usr/bin/p11tool ixr, 127 /usr/bin/pkcs11-tool ixr, 128 /usr/share/p11-kit/modules/ r, 129 /usr/share/p11-kit/modules/* r,`, 130 socketRule)) 131 return nil 132 } 133 134 func (iface *pkcs11Interface) AppArmorPermanentSlot(spec *apparmor.Specification, slot *snap.SlotInfo) error { 135 socketPath, err := iface.getSocketPath(slot) 136 if err != nil { 137 return err 138 } 139 140 // The validation from BeforePrepareSlot() ensures that the socket path starts with "/run/p11-kit" 141 socketRule := fmt.Sprintf(`"/{,var/}%s" rwk,`, socketPath[1:]) 142 spec.AddSnippet(fmt.Sprintf(`# pkcs11 socket dir 143 /{,var/}run/p11-kit/ rw, 144 %s 145 # pkcs11 config 146 /etc/pkcs11/{,**} r, 147 /usr/bin/p11-kit ixr, 148 /usr/bin/p11tool ixr, 149 /usr/bin/pkcs11-tool ixr, 150 /usr/libexec/p11-kit/p11-kit-server ixr, 151 /usr/libexec/p11-kit/p11-kit-remote ixr,`, 152 socketRule)) 153 154 return nil 155 } 156 157 func (iface *pkcs11Interface) AutoConnect(*snap.PlugInfo, *snap.SlotInfo) bool { 158 // allow what declarations allowed 159 return true 160 } 161 162 func init() { 163 registerIface(&pkcs11Interface{}) 164 }