# apparmor.d - Full set of apparmor profiles
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2012 Canonical Ltd.
# Copyright (C) 2015-2016 Simon Deziel
# Copyright (C) 2022-2024 Alexandre Pujol <alexandre@pujol.io>
# SPDX-License-Identifier: GPL-2.0-only

# Adapted from https://gitlab.com/apparmor/apparmor/-/blob/master/profiles/apparmor/profiles/extras/usr.sbin.sshd

# As SSH is used to administrate a server this is limited.
# If you want real protection disallow SSH access.


abi <abi/4.0>,

include <tunables/global>

@{exec_path} = @{bin}/sshd
profile sshd @{exec_path} flags=(attach_disconnected) {
  include <abstractions/base>
  include <abstractions/authentication>
  include <abstractions/bus-system>
  include <abstractions/consoles>
  include <abstractions/hosts_access>
  include <abstractions/nameservice-strict>
  include <abstractions/ssl_certs>
  include <abstractions/wutmp>

  capability audit_write,
  capability chown,
  capability dac_read_search,
  capability dac_override,
  capability fowner,
  capability kill,
  capability net_bind_service,
  capability setgid,
  capability setuid,
  capability sys_chroot,
  capability sys_resource,

  # sshd doesn't require net_admin. libpam-systemd tries to
  # use it if available to set the send/receive buffers size,
  # but will fall back to a non-privileged version if it fails.
  deny capability net_admin,

  network inet  stream,
  network inet6 stream,
  network inet  dgram,
  network inet6 dgram,
  network netlink raw,

  signal (receive) set=(hup) peer=@{p_systemd},

  ptrace (read,trace) peer=@{p_systemd},

  unix (bind) type=stream addr=@@{udbus}/bus/sshd/system,

  dbus send bus=system path=/org/freedesktop/login1
       interface=org.freedesktop.login1.Manager
       member={CreateSession,ReleaseSession,CreateSessionWithPIDFD}
       peer=(name=org.freedesktop.login1, label=systemd-logind),

  @{exec_path} mrix,

  @{bin}/@{shells}            rUx,
  @{bin}/false                rix,
  @{bin}/nologin              rPx,
  @{bin}/passwd               rPx,
  @{lib}/openssh/sftp-server  rPx,
  @{lib}/ssh/sshd-session     rix,

  @{etc_ro}/environment r,
  @{etc_ro}/security/limits.d/{,*.conf} r,
  @{etc_rw}/motd r,
  @{etc_rw}/motd.d/{,**} r,
  /etc/default/locale r,
  /etc/gss/mech.d/{,*} r,
  /etc/issue.net r,
  /etc/legal r,
  /etc/machine-id r,
  /etc/motd r,
  /etc/shells r,

  @{etc_ro}/ssh/sshd_config r,
  @{etc_ro}/ssh/sshd_config.d/{,*} r,
  /etc/ssh/ssh_host_* r,

  /var/lib/lastlog/ r,
  /var/lib/lastlog/* rwk,
  /var/lib/wtmpdb/ r,
  /var/lib/wtmpdb/* rwk,

  # For scp
  owner @{user_download_dirs}/{,**} rwl,
  owner @{user_sync_dirs}/{,**} rwl,

  @{HOME}/@{XDG_SSH_DIR}/authorized_keys{,.*} r,
  owner @{user_cache_dirs}/{,motd*} rw,

  @{att}/@{run}/systemd/sessions/@{int}.ref rw,

        @{run}/faillock/@{user} rwk,
        @{run}/motd.d/{,*} r,
        @{run}/motd.dynamic rw,
        @{run}/motd.dynamic.new rw,
        @{run}/systemd/notify w,
  owner @{run}/sshd{,.init}.pid wl,

  @{sys}/fs/cgroup/*/user/*/@{int}/ rw,
  @{sys}/fs/cgroup/systemd/user.slice/user-@{uid}.slice/session-@{word}.scope/ rw,

        @{PROC}/@{pids}/fd/ r,
        @{PROC}/1/environ r,
        @{PROC}/cmdline r,
  owner @{PROC}/@{pid}/limits r,
  owner @{PROC}/@{pid}/loginuid rw,
  owner @{PROC}/@{pid}/mounts r,
  owner @{PROC}/@{pid}/oom_adj rw,
  owner @{PROC}/@{pid}/oom_score_adj rw,
  owner @{PROC}/@{pid}/uid_map r,

  /dev/ptmx rw,
  /dev/tty@{int} rw,
  /dev/ttyS@{int} rw,

  include if exists <local/sshd>
}

# vim:syntax=apparmor
