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  }