Move all of NixOS to nixos/ in preparation of the repository merge
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
{pkgs, config, ...}:
|
||||
let
|
||||
cfg = config.security.apparmor;
|
||||
in
|
||||
with pkgs.lib;
|
||||
{
|
||||
|
||||
options.security.apparmor.confineSUIDApplications = mkOption {
|
||||
default = true;
|
||||
description = ''
|
||||
Install AppArmor profiles for commonly-used SUID application
|
||||
to mitigate potential privilege escalation attacks due to bugs
|
||||
in such applications.
|
||||
|
||||
Currently available profiles: ping
|
||||
'';
|
||||
};
|
||||
|
||||
config = mkIf (cfg.confineSUIDApplications) {
|
||||
security.apparmor.profiles = [ (pkgs.writeText "ping" ''
|
||||
#include <tunables/global>
|
||||
/var/setuid-wrappers/ping {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/consoles>
|
||||
#include <abstractions/nameservice>
|
||||
|
||||
capability net_raw,
|
||||
capability setuid,
|
||||
network inet raw,
|
||||
|
||||
${pkgs.glibc}/lib/*.so mr,
|
||||
${pkgs.libcap}/lib/libcap.so* mr,
|
||||
${pkgs.attr}/lib/libattr.so* mr,
|
||||
|
||||
${pkgs.iputils}/bin/ping mixr,
|
||||
/var/setuid-wrappers/ping.real r,
|
||||
|
||||
#/etc/modules.conf r,
|
||||
|
||||
## Site-specific additions and overrides. See local/README for details.
|
||||
##include <local/bin.ping>
|
||||
}
|
||||
'') ];
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
{pkgs, config, ...}:
|
||||
|
||||
let
|
||||
cfg = config.security.apparmor;
|
||||
in
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
{
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
security.apparmor = {
|
||||
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Enable AppArmor application security system. Enable only if
|
||||
you want to further improve AppArmor.
|
||||
'';
|
||||
};
|
||||
|
||||
profiles = mkOption {
|
||||
default = [];
|
||||
merge = mergeListOption;
|
||||
description = ''
|
||||
List of file names of AppArmor profiles.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf (cfg.enable) {
|
||||
|
||||
assertions = [ { assertion = config.boot.kernelPackages.kernel.features ? apparmor
|
||||
&& config.boot.kernelPackages.kernel.features.apparmor;
|
||||
message = "AppArmor is enabled, but the kernel doesn't have AppArmor support"; }
|
||||
];
|
||||
|
||||
environment.systemPackages = [ pkgs.apparmor ];
|
||||
|
||||
systemd.services.apparmor = {
|
||||
#wantedBy = [ "basic.target" ];
|
||||
wantedBy = [ "local-fs.target" ];
|
||||
path = [ pkgs.apparmor ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = "yes";
|
||||
ExecStart = concatMapStrings (profile:
|
||||
''${pkgs.apparmor}/sbin/apparmor_parser -rKv -I ${pkgs.apparmor}/etc/apparmor.d/ "${profile}" ; ''
|
||||
) cfg.profiles;
|
||||
ExecStop = concatMapStrings (profile:
|
||||
''${pkgs.apparmor}/sbin/apparmor_parser -Rv -I ${pkgs.apparmor}/etc/apparmor.d/ "${profile}" ; ''
|
||||
) cfg.profiles;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
{
|
||||
|
||||
config = {
|
||||
|
||||
environment.etc =
|
||||
[ { source = "${pkgs.cacert}/etc/ca-bundle.crt";
|
||||
target = "ssl/certs/ca-bundle.crt";
|
||||
}
|
||||
|
||||
# Backward compatibility; may remove at some point.
|
||||
{ source = "${pkgs.cacert}/etc/ca-bundle.crt";
|
||||
target = "ca-bundle.crt";
|
||||
}
|
||||
];
|
||||
|
||||
environment.variables.OPENSSL_X509_CERT_FILE = "/etc/ssl/certs/ca-bundle.crt";
|
||||
environment.variables.CURL_CA_BUNDLE = "/etc/ssl/certs/ca-bundle.crt";
|
||||
environment.variables.GIT_SSL_CAINFO = "/etc/ssl/certs/ca-bundle.crt";
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
# This module provides configuration for the PAM (Pluggable
|
||||
# Authentication Modules) system.
|
||||
|
||||
{config, pkgs, ...}:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
inherit (pkgs) pam_krb5 pam_ccreds;
|
||||
|
||||
pam_ldap = if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap;
|
||||
|
||||
otherService = pkgs.writeText "other.pam"
|
||||
''
|
||||
auth required pam_warn.so
|
||||
auth required pam_deny.so
|
||||
account required pam_warn.so
|
||||
account required pam_deny.so
|
||||
password required pam_warn.so
|
||||
password required pam_deny.so
|
||||
session required pam_warn.so
|
||||
session required pam_deny.so
|
||||
'';
|
||||
|
||||
# Create a limits.conf(5) file.
|
||||
makeLimitsConf = limits:
|
||||
pkgs.writeText "limits.conf"
|
||||
(concatStringsSep "\n"
|
||||
(map ({ domain, type, item, value }:
|
||||
concatStringsSep " " [ domain type item value ])
|
||||
limits));
|
||||
|
||||
motd = pkgs.writeText "motd" config.users.motd;
|
||||
|
||||
makePAMService =
|
||||
{ name
|
||||
, # If set, root doesn't need to authenticate (e.g. for the "chsh"
|
||||
# service).
|
||||
rootOK ? false
|
||||
, # If set, user listed in /etc/pamusb.conf are able to log in with
|
||||
# the associated usb key.
|
||||
usbAuth ? config.security.pam.usb.enable
|
||||
, # If set, OTPW system will be used (if ~/.otpw exists)
|
||||
otpwAuth ? config.security.pam.enableOTPW
|
||||
, # If set, the calling user's SSH agent is used to authenticate
|
||||
# against the keys in the calling user's ~/.ssh/authorized_keys.
|
||||
# This is useful for "sudo" on password-less remote systems.
|
||||
sshAgentAuth ? false
|
||||
, # If set, the service will register a new session with systemd's
|
||||
# login manager. If the service is running locally, this will
|
||||
# give the user ownership of audio devices etc.
|
||||
startSession ? false
|
||||
, # Set the login uid of the process (/proc/self/loginuid) for
|
||||
# auditing purposes. The login uid is only set by "entry
|
||||
# points" like login and sshd, not by commands like sudo.
|
||||
setLoginUid ? startSession
|
||||
, # Whether to forward XAuth keys between users. Mostly useful
|
||||
# for "su".
|
||||
forwardXAuth ? false
|
||||
, # Whether to allow logging into accounts that have no password
|
||||
# set (i.e., have an empty password field in /etc/passwd or
|
||||
# /etc/group). This does not enable logging into disabled
|
||||
# accounts (i.e., that have the password field set to `!').
|
||||
# Note that regardless of what the pam_unix documentation says,
|
||||
# accounts with hashed empty passwords are always allowed to log
|
||||
# in.
|
||||
allowNullPassword ? false
|
||||
, # The limits, as per limits.conf(5).
|
||||
limits ? config.security.pam.loginLimits
|
||||
, # Whether to show the message of the day.
|
||||
showMotd ? false
|
||||
, # Whether to update /var/log/wtmp.
|
||||
updateWtmp ? false
|
||||
}:
|
||||
|
||||
{ source = pkgs.writeText "${name}.pam"
|
||||
# !!! TODO: move the LDAP stuff to the LDAP module, and the
|
||||
# Samba stuff to the Samba module. This requires that the PAM
|
||||
# module provides the right hooks.
|
||||
''
|
||||
# Account management.
|
||||
account sufficient pam_unix.so
|
||||
${optionalString config.users.ldap.enable
|
||||
"account sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
|
||||
${optionalString config.krb5.enable
|
||||
"account sufficient ${pam_krb5}/lib/security/pam_krb5.so"}
|
||||
|
||||
# Authentication management.
|
||||
${optionalString rootOK
|
||||
"auth sufficient pam_rootok.so"}
|
||||
${optionalString (config.security.pam.enableSSHAgentAuth && sshAgentAuth)
|
||||
"auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=~/.ssh/authorized_keys:~/.ssh/authorized_keys2:/etc/ssh/authorized_keys.d/%u"}
|
||||
${optionalString usbAuth
|
||||
"auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so"}
|
||||
auth sufficient pam_unix.so ${optionalString allowNullPassword "nullok"} likeauth
|
||||
${optionalString otpwAuth
|
||||
"auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so"}
|
||||
${optionalString config.users.ldap.enable
|
||||
"auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass"}
|
||||
${optionalString config.krb5.enable ''
|
||||
auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass
|
||||
auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass
|
||||
auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass
|
||||
''}
|
||||
auth required pam_deny.so
|
||||
|
||||
# Password management.
|
||||
password requisite pam_unix.so nullok sha512
|
||||
${optionalString config.users.ldap.enable
|
||||
"password sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
|
||||
${optionalString config.krb5.enable
|
||||
"password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass"}
|
||||
${optionalString config.services.samba.syncPasswordsByPam
|
||||
"password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass"}
|
||||
|
||||
# Session management.
|
||||
session required pam_unix.so
|
||||
${optionalString updateWtmp
|
||||
"session required ${pkgs.pam}/lib/security/pam_lastlog.so silent"}
|
||||
${optionalString config.users.ldap.enable
|
||||
"session optional ${pam_ldap}/lib/security/pam_ldap.so"}
|
||||
${optionalString config.krb5.enable
|
||||
"session optional ${pam_krb5}/lib/security/pam_krb5.so"}
|
||||
${optionalString otpwAuth
|
||||
"session optional ${pkgs.otpw}/lib/security/pam_otpw.so"}
|
||||
${optionalString startSession
|
||||
"session optional ${pkgs.systemd}/lib/security/pam_systemd.so"}
|
||||
${optionalString setLoginUid
|
||||
"session required pam_loginuid.so"}
|
||||
${optionalString forwardXAuth
|
||||
"session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99"}
|
||||
${optionalString (limits != [])
|
||||
"session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf limits}"}
|
||||
${optionalString (showMotd && config.users.motd != null)
|
||||
"session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd}"}
|
||||
'';
|
||||
target = "pam.d/${name}";
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
security.pam.loginLimits = mkOption {
|
||||
default = [];
|
||||
example =
|
||||
[ { domain = "ftp";
|
||||
type = "hard";
|
||||
item = "nproc";
|
||||
value = "0";
|
||||
}
|
||||
{ domain = "@student";
|
||||
type = "-";
|
||||
item = "maxlogins";
|
||||
value = "4";
|
||||
}
|
||||
];
|
||||
|
||||
description =
|
||||
'' Define resource limits that should apply to users or groups.
|
||||
Each item in the list should be an attribute set with a
|
||||
<varname>domain</varname>, <varname>type</varname>,
|
||||
<varname>item</varname>, and <varname>value</varname>
|
||||
attribute. The syntax and semantics of these attributes
|
||||
must be that described in the limits.conf(5) man page.
|
||||
'';
|
||||
};
|
||||
|
||||
security.pam.services = mkOption {
|
||||
default = [];
|
||||
example = [
|
||||
{ name = "chsh"; rootOK = true; }
|
||||
{ name = "login"; startSession = true; allowNullPassword = true;
|
||||
limits = [
|
||||
{ domain = "ftp";
|
||||
type = "hard";
|
||||
item = "nproc";
|
||||
value = "0";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
|
||||
description =
|
||||
''
|
||||
This option defines the PAM services. A service typically
|
||||
corresponds to a program that uses PAM,
|
||||
e.g. <command>login</command> or <command>passwd</command>.
|
||||
Each element of this list is an attribute set describing a
|
||||
service. The attribute <varname>name</varname> specifies
|
||||
the name of the service. The attribute
|
||||
<varname>rootOK</varname> specifies whether the root user is
|
||||
allowed to use this service without authentication. The
|
||||
attribute <varname>startSession</varname> specifies whether
|
||||
systemd's PAM connector module should be used to start a new
|
||||
session; for local sessions, this will give the user
|
||||
ownership of devices such as audio and CD-ROM drives. The
|
||||
attribute <varname>forwardXAuth</varname> specifies whether
|
||||
X authentication keys should be passed from the calling user
|
||||
to the target user (e.g. for <command>su</command>).
|
||||
|
||||
The attribute <varname>limits</varname> defines resource limits
|
||||
that should apply to users or groups for the service. Each item in
|
||||
the list should be an attribute set with a
|
||||
<varname>domain</varname>, <varname>type</varname>,
|
||||
<varname>item</varname>, and <varname>value</varname> attribute.
|
||||
The syntax and semantics of these attributes must be that described
|
||||
in the limits.conf(5) man page.
|
||||
'';
|
||||
};
|
||||
|
||||
security.pam.enableSSHAgentAuth = mkOption {
|
||||
default = false;
|
||||
description =
|
||||
''
|
||||
Enable sudo logins if the user's SSH agent provides a key
|
||||
present in <filename>~/.ssh/authorized_keys</filename>.
|
||||
This allows machines to exclusively use SSH keys instead of
|
||||
passwords.
|
||||
'';
|
||||
};
|
||||
|
||||
security.pam.enableOTPW = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Enable the OTPW (one-time password) PAM module
|
||||
'';
|
||||
};
|
||||
|
||||
users.motd = mkOption {
|
||||
default = null;
|
||||
example = "Today is Sweetmorn, the 4th day of The Aftermath in the YOLD 3178.";
|
||||
type = types.nullOr types.string;
|
||||
description = "Message of the day shown to users when they log in.";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = {
|
||||
|
||||
environment.systemPackages =
|
||||
# Include the PAM modules in the system path mostly for the manpages.
|
||||
[ pkgs.pam ]
|
||||
++ optional config.users.ldap.enable pam_ldap
|
||||
++ optionals config.krb5.enable [pam_krb5 pam_ccreds]
|
||||
++ optionals config.security.pam.enableOTPW [ pkgs.otpw ];
|
||||
|
||||
environment.etc =
|
||||
map makePAMService config.security.pam.services
|
||||
++ singleton
|
||||
{ source = otherService;
|
||||
target = "pam.d/other";
|
||||
};
|
||||
|
||||
security.setuidOwners = [ {
|
||||
program = "unix_chkpwd";
|
||||
source = "${pkgs.pam}/sbin/unix_chkpwd.orig";
|
||||
owner = "root";
|
||||
setuid = true;
|
||||
} ];
|
||||
|
||||
security.pam.services =
|
||||
# Most of these should be moved to specific modules.
|
||||
[ { name = "cups"; }
|
||||
{ name = "ejabberd"; }
|
||||
{ name = "ftp"; }
|
||||
{ name = "i3lock"; }
|
||||
{ name = "lshd"; }
|
||||
{ name = "samba"; }
|
||||
{ name = "screen"; }
|
||||
{ name = "vlock"; }
|
||||
{ name = "xlock"; }
|
||||
{ name = "xscreensaver"; }
|
||||
];
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{config, pkgs, ...}:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
inherit (pkgs) pam_usb;
|
||||
|
||||
cfg = config.security.pam.usb;
|
||||
|
||||
anyUsbAuth = any (attrByPath ["usbAuth"] false) config.security.pam.services;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
options = {
|
||||
|
||||
security.pam.usb = {
|
||||
enable = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Enable USB login for all login system unless the service disabled
|
||||
it. For more information, visit <link
|
||||
xlink:href="http://pamusb.org/doc/quickstart#setting_up" />.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
config = mkIf (cfg.enable || anyUsbAuth) {
|
||||
|
||||
# pmount need to have a set-uid bit to make pam_usb works in user
|
||||
# environment. (like su, sudo)
|
||||
|
||||
security.setuidPrograms = [ "pmount" "pumount" ];
|
||||
environment.systemPackages = [ pkgs.pmount ];
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.security.polkit;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
options = {
|
||||
|
||||
security.polkit.enable = mkOption {
|
||||
default = true;
|
||||
description = "Whether to enable PolKit.";
|
||||
};
|
||||
|
||||
security.polkit.permissions = mkOption {
|
||||
default = "";
|
||||
example =
|
||||
''
|
||||
[Disallow Users To Suspend]
|
||||
Identity=unix-group:users
|
||||
Action=org.freedesktop.upower.*
|
||||
ResultAny=no
|
||||
ResultInactive=no
|
||||
ResultActive=no
|
||||
|
||||
[Allow Anybody To Eject Disks]
|
||||
Identity=unix-user:*
|
||||
Action=org.freedesktop.udisks.drive-eject
|
||||
ResultAny=yes
|
||||
ResultInactive=yes
|
||||
ResultActive=yes
|
||||
|
||||
[Allow Alice To Mount Filesystems After Admin Authentication]
|
||||
Identity=unix-user:alice
|
||||
Action=org.freedesktop.udisks.filesystem-mount
|
||||
ResultAny=auth_admin
|
||||
ResultInactive=auth_admin
|
||||
ResultActive=auth_admin
|
||||
'';
|
||||
description =
|
||||
''
|
||||
Allows the default permissions of privileged actions to be overridden.
|
||||
'';
|
||||
};
|
||||
|
||||
security.polkit.adminIdentities = mkOption {
|
||||
default = "unix-user:0;unix-group:wheel";
|
||||
example = "";
|
||||
description =
|
||||
''
|
||||
Specifies which users are considered “administrators”, for those
|
||||
actions that require the user to authenticate as an
|
||||
administrator (i.e. have an <literal>auth_admin</literal>
|
||||
value). By default, this is the <literal>root</literal>
|
||||
user and all users in the <literal>wheel</literal> group.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.polkit ];
|
||||
|
||||
# The polkit daemon reads action files
|
||||
environment.pathsToLink = [ "/share/polkit-1/actions" ];
|
||||
|
||||
environment.etc =
|
||||
[ # No idea what the "null backend" is, but it seems to need this.
|
||||
{ source = "${pkgs.polkit}/etc/polkit-1/nullbackend.conf.d";
|
||||
target = "polkit-1/nullbackend.conf.d";
|
||||
}
|
||||
|
||||
# This file determines what users are considered
|
||||
# "administrators".
|
||||
{ source = pkgs.writeText "10-nixos.conf"
|
||||
''
|
||||
[Configuration]
|
||||
AdminIdentities=${cfg.adminIdentities}
|
||||
'';
|
||||
target = "polkit-1/localauthority.conf.d/10-nixos.conf";
|
||||
}
|
||||
|
||||
{ source = pkgs.writeText "org.nixos.pkla" cfg.permissions;
|
||||
target = "polkit-1/localauthority/10-vendor.d/org.nixos.pkla";
|
||||
}
|
||||
];
|
||||
|
||||
services.dbus.packages = [ pkgs.polkit ];
|
||||
|
||||
security.pam.services = [ { name = "polkit-1"; } ];
|
||||
|
||||
security.setuidPrograms = [ "pkexec" ];
|
||||
|
||||
security.setuidOwners = singleton
|
||||
{ program = "polkit-agent-helper-1";
|
||||
owner = "root";
|
||||
group = "root";
|
||||
setuid = true;
|
||||
source = "${pkgs.polkit}/libexec/polkit-1/polkit-agent-helper-1";
|
||||
};
|
||||
|
||||
system.activationScripts.polkit =
|
||||
''
|
||||
mkdir -p /var/lib/polkit-1/localauthority
|
||||
chmod 700 /var/lib/polkit-1{/localauthority,}
|
||||
|
||||
# Force polkitd to be restarted so that it reloads its
|
||||
# configuration.
|
||||
${pkgs.procps}/bin/pkill -INT -u root -x polkitd
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
{
|
||||
options = {
|
||||
security.rngd.enable = mkOption {
|
||||
default = true;
|
||||
description = ''
|
||||
Whether to enable the rng daemon, which adds entropy from
|
||||
hardware sources of randomness to the kernel entropy pool when
|
||||
available.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf config.security.rngd.enable {
|
||||
services.udev.extraRules = ''
|
||||
KERNEL=="random", TAG+="systemd"
|
||||
SUBSYSTEM=="cpu", ENV{MODALIAS}=="x86cpu:*feature:*009E*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service"
|
||||
KERNEL=="hw_random", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service"
|
||||
KERNEL=="tmp0", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rngd.service"
|
||||
'';
|
||||
|
||||
systemd.services.rngd = {
|
||||
bindsTo = [ "dev-random.device" ];
|
||||
|
||||
after = [ "dev-random.device" ];
|
||||
|
||||
description = "Hardware RNG Entropy Gatherer Daemon";
|
||||
|
||||
serviceConfig.ExecStart = "${pkgs.rng_tools}/sbin/rngd -f";
|
||||
|
||||
restartTriggers = [ pkgs.rng_tools ];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
# A module for ‘rtkit’, a DBus system service that hands out realtime
|
||||
# scheduling priority to processes that ask for it.
|
||||
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
{
|
||||
|
||||
options = {
|
||||
|
||||
security.rtkit.enable = mkOption {
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to enable the RealtimeKit system service, which hands
|
||||
out realtime scheduling priority to user processes on
|
||||
demand. For example, the PulseAudio server uses this to
|
||||
acquire realtime priority.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
config = mkIf config.security.rtkit.enable {
|
||||
|
||||
environment.systemPackages = [ pkgs.rtkit ];
|
||||
|
||||
services.dbus.packages = [ pkgs.rtkit ];
|
||||
|
||||
users.extraUsers = singleton
|
||||
{ name = "rtkit";
|
||||
uid = config.ids.uids.rtkit;
|
||||
description = "RealtimeKit daemon";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <dirent.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Make sure assertions are not compiled out. */
|
||||
#undef NDEBUG
|
||||
|
||||
extern char **environ;
|
||||
|
||||
static char * wrapperDir = WRAPPER_DIR;
|
||||
|
||||
int main(int argc, char * * argv)
|
||||
{
|
||||
char self[PATH_MAX];
|
||||
|
||||
int len = readlink("/proc/self/exe", self, sizeof(self) - 1);
|
||||
assert (len > 0);
|
||||
self[len] = 0;
|
||||
|
||||
/* Make sure that we are being executed from the right location,
|
||||
i.e., `wrapperDir'. This is to prevent someone from
|
||||
creating hard link `X' from some other location, along with a
|
||||
false `X.real' file, to allow arbitrary programs from being
|
||||
executed setuid. */
|
||||
assert ((strncmp(self, wrapperDir, sizeof(wrapperDir)) == 0) &&
|
||||
(self[strlen(wrapperDir)] == '/'));
|
||||
|
||||
/* Make *really* *really* sure that we were executed as `self',
|
||||
and not, say, as some other setuid program. That is, our
|
||||
effective uid/gid should match the uid/gid of `self'. */
|
||||
//printf("%d %d\n", geteuid(), getegid());
|
||||
|
||||
struct stat st;
|
||||
assert (lstat(self, &st) != -1);
|
||||
|
||||
//printf("%d %d\n", st.st_uid, st.st_gid);
|
||||
|
||||
assert ((st.st_mode & S_ISUID) == 0 ||
|
||||
(st.st_uid == geteuid()));
|
||||
|
||||
assert ((st.st_mode & S_ISGID) == 0 ||
|
||||
st.st_gid == getegid());
|
||||
|
||||
/* And, of course, we shouldn't be writable. */
|
||||
assert (!(st.st_mode & (S_IWGRP | S_IWOTH)));
|
||||
|
||||
|
||||
/* Read the path of the real (wrapped) program from <self>.real. */
|
||||
char realFN[PATH_MAX + 10];
|
||||
int realFNSize = snprintf (realFN, sizeof(realFN), "%s.real", self);
|
||||
assert (realFNSize < sizeof(realFN));
|
||||
|
||||
int fdSelf = open(realFN, O_RDONLY);
|
||||
assert (fdSelf != -1);
|
||||
|
||||
char real[PATH_MAX];
|
||||
len = read(fdSelf, real, PATH_MAX);
|
||||
assert (len != -1);
|
||||
assert (len < sizeof (real));
|
||||
assert (len > 0);
|
||||
real[len] = 0;
|
||||
|
||||
close(fdSelf);
|
||||
|
||||
//printf("real = %s, len = %d\n", real, len);
|
||||
|
||||
execve(real, argv, environ);
|
||||
|
||||
fprintf(stderr, "%s: cannot run `%s': %s\n",
|
||||
argv[0], real, strerror(errno));
|
||||
|
||||
exit(1);
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
{pkgs, config, ...}:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
inherit (config.security) wrapperDir;
|
||||
|
||||
setuidWrapper = pkgs.stdenv.mkDerivation {
|
||||
name = "setuid-wrapper";
|
||||
buildCommand = ''
|
||||
ensureDir $out/bin
|
||||
gcc -Wall -O2 -DWRAPPER_DIR=\"${wrapperDir}\" \
|
||||
${./setuid-wrapper.c} -o $out/bin/setuid-wrapper
|
||||
strip -s $out/bin/setuid-wrapper
|
||||
'';
|
||||
};
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
security.setuidPrograms = mkOption {
|
||||
default = [];
|
||||
description = ''
|
||||
The Nix store cannot contain setuid/setgid programs directly.
|
||||
For this reason, NixOS can automatically generate wrapper
|
||||
programs that have the necessary privileges. This option
|
||||
lists the names of programs in the system environment for
|
||||
which setuid root wrappers should be created.
|
||||
'';
|
||||
};
|
||||
|
||||
security.setuidOwners = mkOption {
|
||||
default = [];
|
||||
example =
|
||||
[ { program = "sendmail";
|
||||
owner = "nobody";
|
||||
group = "postdrop";
|
||||
setuid = false;
|
||||
setgid = true;
|
||||
}
|
||||
];
|
||||
description = ''
|
||||
This option allows the ownership and permissions on the setuid
|
||||
wrappers for specific programs to be overridden from the
|
||||
default (setuid root, but not setgid root).
|
||||
'';
|
||||
};
|
||||
|
||||
security.wrapperDir = mkOption {
|
||||
default = "/var/setuid-wrappers";
|
||||
description = ''
|
||||
This option defines the path to the setuid wrappers. It
|
||||
should generally not be overriden. Some packages in Nixpkgs
|
||||
expect that <option>wrapperDir</option> is
|
||||
<filename>/var/setuid-wrappers</filename>.
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = {
|
||||
|
||||
security.setuidPrograms =
|
||||
[ "fusermount" "wodim" "cdrdao" "growisofs" ];
|
||||
|
||||
system.activationScripts.setuid =
|
||||
let
|
||||
setuidPrograms =
|
||||
(map (x: { program = x; owner = "root"; group = "root"; setuid = true; })
|
||||
config.security.setuidPrograms)
|
||||
++ config.security.setuidOwners;
|
||||
|
||||
makeSetuidWrapper =
|
||||
{ program
|
||||
, source ? ""
|
||||
, owner ? "nobody"
|
||||
, group ? "nogroup"
|
||||
, setuid ? false
|
||||
, setgid ? false
|
||||
, permissions ? "u+rx,g+x,o+x"
|
||||
}:
|
||||
|
||||
''
|
||||
source=${if source != "" then source else "$(PATH=$SETUID_PATH type -tP ${program})"}
|
||||
if test -z "$source"; then
|
||||
# If we can't find the program, fall back to the
|
||||
# system profile.
|
||||
source=/nix/var/nix/profiles/default/bin/${program}
|
||||
fi
|
||||
|
||||
cp ${setuidWrapper}/bin/setuid-wrapper ${wrapperDir}/${program}
|
||||
echo -n "$source" > ${wrapperDir}/${program}.real
|
||||
chmod 0000 ${wrapperDir}/${program} # to prevent races
|
||||
chown ${owner}.${group} ${wrapperDir}/${program}
|
||||
chmod "u${if setuid then "+" else "-"}s,g${if setgid then "+" else "-"}s,${permissions}" ${wrapperDir}/${program}
|
||||
'';
|
||||
|
||||
in stringAfter [ "users" ]
|
||||
''
|
||||
# Look in the system path and in the default profile for
|
||||
# programs to be wrapped.
|
||||
SETUID_PATH=${config.system.path}/bin:${config.system.path}/sbin
|
||||
|
||||
if test -d ${wrapperDir}; then rm -f ${wrapperDir}/*; fi # */
|
||||
mkdir -p ${wrapperDir}
|
||||
|
||||
${concatMapStrings makeSetuidWrapper setuidPrograms}
|
||||
'';
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{pkgs, config, ...}:
|
||||
|
||||
with pkgs.lib;
|
||||
|
||||
let
|
||||
|
||||
cfg = config.security.sudo;
|
||||
|
||||
inherit (pkgs) sudo;
|
||||
|
||||
in
|
||||
|
||||
{
|
||||
|
||||
###### interface
|
||||
|
||||
options = {
|
||||
|
||||
security.sudo.enable = mkOption {
|
||||
default = true;
|
||||
description =
|
||||
''
|
||||
Whether to enable the <command>sudo</command> command, which
|
||||
allows non-root users to execute commands as root.
|
||||
'';
|
||||
};
|
||||
|
||||
security.sudo.wheelNeedsPassword = mkOption {
|
||||
default = true;
|
||||
description =
|
||||
''
|
||||
Whether users of the <code>wheel</code> group can execute
|
||||
commands as super user without entering a password.
|
||||
'';
|
||||
};
|
||||
|
||||
security.sudo.configFile = mkOption {
|
||||
# Note: if syntax errors are detected in this file, the NixOS
|
||||
# configuration will fail to build.
|
||||
description =
|
||||
''
|
||||
This string contains the contents of the
|
||||
<filename>sudoers</filename> file.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
###### implementation
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
|
||||
security.sudo.configFile =
|
||||
''
|
||||
# Don't edit this file. Set the NixOS option ‘security.sudo.configFile’ instead.
|
||||
|
||||
# Environment variables to keep for root and %wheel.
|
||||
Defaults:root,%wheel env_keep+=LOCALE_ARCHIVE
|
||||
Defaults:root,%wheel env_keep+=NIX_CONF_DIR
|
||||
Defaults:root,%wheel env_keep+=NIX_PATH
|
||||
Defaults:root,%wheel env_keep+=TERMINFO_DIRS
|
||||
|
||||
# Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic.
|
||||
Defaults env_keep+=SSH_AUTH_SOCK
|
||||
|
||||
# "root" is allowed to do anything.
|
||||
root ALL=(ALL) SETENV: ALL
|
||||
|
||||
# Users in the "wheel" group can do anything.
|
||||
%wheel ALL=(ALL) ${if cfg.wheelNeedsPassword then "" else "NOPASSWD: ALL, "}SETENV: ALL
|
||||
'';
|
||||
|
||||
security.setuidPrograms = [ "sudo" "sudoedit" ];
|
||||
|
||||
environment.systemPackages = [ sudo ];
|
||||
|
||||
security.pam.services = [ { name = "sudo"; sshAgentAuth = true; } ];
|
||||
|
||||
environment.etc = singleton
|
||||
{ source = pkgs.writeText "sudoers-in" cfg.configFile;
|
||||
# Make sure that the sudoers file is syntactically valid.
|
||||
# (currently disabled - NIXOS-66)
|
||||
#"${pkgs.sudo}/sbin/visudo -f $src -c && cp $src $out";
|
||||
target = "sudoers";
|
||||
mode = "0440";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user