Previously we were setting GRKERNSEC_PROC_USER y, which was a little bit
too strict. It doesn't allow a special group (e.g. the grsecurity group
users) to access /proc information - this requires
GRKERNSEC_PROC_USERGROUP y, and the two are mutually exclusive.
This was also not in line with the default automatic grsecurity
configuration - it actually defaults to USERGROUP (although it has a
default GID of 1001 instead of ours), not USER.
This introduces a new option restrictProcWithGroup - enabled by default
- which turns on GRKERNSEC_PROC_USERGROUP instead. It also turns off
restrictProc by default and makes sure both cannot be enabled.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
This module implements a significant refactoring in grsecurity
configuration for NixOS, making it far more usable by default and much
easier to configure.
- New security.grsecurity NixOS attributes.
- All grsec kernels supported
- Allows default 'auto' grsec configuration, or custom config
- Supports custom kernel options through kernelExtraConfig
- Defaults to high-security - user must choose kernel, server/desktop
mode, and any virtualisation software. That's all.
- kptr_restrict is fixed under grsecurity (it's unwriteable)
- grsecurity patch creation is now significantly abstracted
- only need revision, version, and SHA1
- kernel version requirements are asserted for sanity
- built kernels can have the uname specify the exact grsec version
for development or bug reports. Off by default (requires
`security.grsecurity.config.verboseVersion = true;`)
- grsecurity sysctl support
- By default, disabled.
- For people who enable it, NixOS deploys a 'grsec-lock' systemd
service which runs at startup. You are expected to configure sysctl
through NixOS like you regularly would, which will occur before the
service is started. As a result, changing sysctl settings requires
a reboot.
- New default group: 'grsecurity'
- Root is a member by default
- GRKERNSEC_PROC_GID is implicitly set to the 'grsecurity' GID,
making it possible to easily add users to this group for /proc
access
- AppArmor is now automatically enabled where it wasn't before, despite
implying features.apparmor = true
The most trivial example of enabling grsecurity in your kernel is by
specifying:
security.grsecurity.enable = true;
security.grsecurity.testing = true; # testing 3.13 kernel
security.grsecurity.config.system = "desktop"; # or "server"
This specifies absolutely no virtualisation support. In general, you
probably at least want KVM host support, which is a little more work.
So:
security.grsecurity.enable = true;
security.grsecurity.stable = true; # enable stable 3.2 kernel
security.grsecurity.config = {
system = "server";
priority = "security";
virtualisationConfig = "host";
virtualisationSoftware = "kvm";
hardwareVirtualisation = true;
}
This module has primarily been tested on Hetzner EX40 & VQ7 servers
using NixOps.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
This prevents errors like "Another app is currently holding the
xtables lock" if the firewall and NAT services are starting in
parallel. (Longer term, we should probably move to a single service
for managing the iptables rules.)
This allows to easily override the used PHP package, especially for
example if you want to use PHP 5.5 or if you want to override the
derivation.
Signed-off-by: aszlig <aszlig@redmoonstudios.org>
The postgresql module has a postStart section that waits for a database
to accept connections before continuing. However, this assumes various
properties about the database - specifically the database user
and (implicitly) the database name. This means that for old
installations, this command fails because there is no 'postgres' user,
and the service never starts.
While 7deff39 does create the 'postgres' user, a better solution is to
use `pg_isready`, who's sole purpose is to check if the database is
accepting connections. This has no dependency on users, so should be
more robust.
Old PostgreSQL installations were created using the 'root' database
user. In this case, we need to create a new 'postgres' account, as we
now assume that this is the superuser account.
Unfortunately, these machines will be left with a 'root' user as
well (which will have ownership of some databases). While PostgreSQL
does let you rename superuser accounts, you can only do that when you
are connected as a *different* database user. Thus we'd have to create a
special superuser account to do the renaming. As we default to using
ident authentication, we would have to create a system level user to do
this. This all feels rather complex, so I'm currently opting to keep the
'root' user on these old machines.
This allows to define systemd.path(5) units, for example like this:
{
systemd = let
description = "Set Key Permissions for xyz.key";
in {
paths.set-key-perms = {
inherit description;
before = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
pathConfig.PathChanged = "/run/keys/xyz.key";
};
services.set-key-perms = {
inherit description;
serviceConfig.Type = "oneshot";
script = "chown myspecialkeyuser /run/keys/xyz.key";
};
};
}
The example here is actually useful in order to set permissions for the
NixOps keys target to ensure those permisisons aren't reset whenever the
key file is reuploaded.
Signed-off-by: aszlig <aszlig@redmoonstudios.org>
as per postgresql manual, interactions with psql should be carried
out with the postgresql system user and postgresql db user by default.
ensure it happens in postStart.
This reverts commit f7d5e83abb. It
breaks the Firefox and Xfce tests:
in job ‘tests.firefox.x86_64-linux’:
cannot coerce a boolean to a string
in job ‘tests.xfce.x86_64-linux’:
infinite recursion encountered
Update VirtualBox (and implicitly VirtualBox Guest Additions) to 4.3.6
and Oracle VM VirtualBox Extension Pack to 91406
Conflicts due to minor upgrade in the mean time
Conflicts:
nixos/modules/virtualisation/virtualbox-guest.nix
pkgs/applications/virtualization/virtualbox/default.nix
pkgs/applications/virtualization/virtualbox/guest-additions/default.nix
Needed for the installer tests, since otherwise mounting a filesystem
may fail as it has a last-mounted date in the future.
http://hydra.nixos.org/build/9846712
Latest update to udisks in 344f2e65 broke it for me. Fix it by doing the
following:
- Add udisks.service to /etc/systemd/system (via systemd.packages)
- Fix path to udisks-daemon in udisks.service (libexec/ instead of lib/)
- Make dhcp work, use dhcpcd without udev in container
- Make login shell work, patch getty to not wait for /dev/tty0
- Make ssh work, sshd/pam do not start session
The command nixos-container can now create containers. For instance,
the following creates and starts a container named ‘database’:
$ nixos-container create database
The configuration of the container is stored in
/var/lib/containers/<name>/etc/nixos/configuration.nix. After editing
the configuration, you can make the changes take effect by doing
$ nixos-container update database
The container can also be destroyed:
$ nixos-container destroy database
Containers are now executed using a template unit,
‘container@.service’, so the unit in this example would be
‘container@database.service’.
According to the MySQL manual, this is a perfectly legal way of
shutting down the server. The shutdown logs also looks fine:
systemd[1]: Stopping MySQL Server...
mysqld[5114]: 140319 8:36:12 [Note] /nix/store/sc26mz82k97mbpx3d1abzn3rrbd155ws-mariadb-10.0.8/bin/mysqld: Normal shutdown
mysqld[5114]: 140319 8:36:12 [Note] Event Scheduler: Purging the queue. 0 events
mysqld[5114]: 140319 8:36:12 [Note] InnoDB: FTS optimize thread exiting.
mysqld[5114]: 140319 8:36:12 [Note] InnoDB: Starting shutdown...
mysqld[5114]: 140319 8:36:14 [Note] InnoDB: Shutdown completed; log sequence number 1619078
mysqld[5114]: 140319 8:36:14 [Note] /nix/store/sc26mz82k97mbpx3d1abzn3rrbd155ws-mariadb-10.0.8/bin/mysqld: Shutdown complete
systemd[1]: Stopped MySQL Server.
For example, the following sets up a container named ‘foo’. The
container will have a single network interface eth0, with IP address
10.231.136.2. The host will have an interface c-foo with IP address
10.231.136.1.
systemd.containers.foo =
{ privateNetwork = true;
hostAddress = "10.231.136.1";
localAddress = "10.231.136.2";
config =
{ services.openssh.enable = true; };
};
With ‘privateNetwork = true’, the container has the CAP_NET_ADMIN
capability, allowing it to do arbitrary network configuration, such as
setting up firewall rules. This is secure because it cannot touch the
interfaces of the host.
The helper program ‘run-in-netns’ is needed at the moment because ‘ip
netns exec’ doesn't quite do the right thing (it remounts /sys without
bind-mounting the original /sys/fs/cgroups).
These are stored on the host in
/nix/var/nix/{profiles,gcroots}/per-container/<container-name> to
ensure that container profiles/roots are not garbage-collected.
This has the unintended side-effect of restarting httpd every time we
run switch-to-configuration, even if httpd hasn't changed (because
we're doing a "stop keys.target" now). So use a "Wants" dependency
instead.
On the host, you can run
$ socat unix:<path-to-container>/var/lib/login.socket -,echo=0,raw
to get a login prompt. So this allows logging in even if the
container has no SSH access enabled.
You can also do
$ socat unix:<path-to-container>/var/lib/root-shell.socket -
to get a plain root shell. (This socket is only accessible by root,
obviously.) This makes it easy to execute commands in the container,
e.g.
$ echo reboot | socat unix:<path-to-container>/var/lib/root-shell.socket -
This reverts commit b792394119.
Starting the manual on tty8 was intended as a convenience during
installation, not as a general purpose thing. In fact, given that w3m
runs as root, this is highly insecure!
This module adds the security.duosec attributes, which you can use to
enable simple two-factor authentication for NixOS logins.
The module currently provides PAM and SSH support, although the PAM unix
system configuration isn't automatically dealt with (although the
configuration is automatically built).
Enabling it is as easy as saying:
security.duosec.ssh.enable = true;
security.duosec.ikey = "XXXXXXXX...";
security.duosec.skey = "XXXXXXXX...";
security.duosec.host = "api-XXXXXXX.duosecurity.com";
security.duosec.group = "duosec";
which will enforce two-factor authentication for SSH logins for users in
the 'duosec' group.
This requires uid/gid support in the environment.etc module.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
This has the nice side-effect of making gpsd actually run!
Old behaviour (debugLevel=2):
systemd[1]: gpsd.service holdoff time over, scheduling restart.
systemd[1]: Stopping GPSD daemon...
systemd[1]: Starting GPSD daemon...
systemd[1]: gpsd.service start request repeated too quickly, refusing to start.
systemd[1]: Failed to start GPSD daemon.
systemd[1]: Unit gpsd.service entered failed state.
New behaviour (debugLevel=2):
gpsd[945]: gpsd: launching (Version 2.95)
systemd[1]: Started GPSD daemon.
gpsd[945]: gpsd: listening on port 2947
gpsd[945]: gpsd: running with effective group ID 27
gpsd[945]: gpsd: running with effective user ID 23
gpsd[945]: gpsd: stashing device /dev/ttyUSB0 at slot 0
Uses standard NixOS user config merging.
Work in progress: The slave config does not actually start the slave agent. This just configures a
jenkins user if required. Bare minimum to enable a nice jenkins SSH slave.
By default the jenkins server is executed under the user "jenkins". Which can be configured using
users.jenkins.* options. If a different user is requested by changing services.jenkins.user then
none of the users.jenkins options apply.
This patch does not include jenkins slave configuration. Some config options will probably change
when this is implemented.
Aspects like the user and environment are typically identical between slave and master. The service
configs are different. The design is for users.jenkins to cover the shared aspects while
services.jenkins and services.jenkins-slave cover the master and slave specific aspects,
respectively.
Another option would be to place everything under services.jenkins and have a config that selects
master vs slave.
You can now say:
systemd.services.foo.baseUnit = "${pkgs.foo}/.../foo.service";
This will cause NixOS' generated foo.service file to include
foo.service from the foo package. You can then apply local
customization in the usual way:
systemd.services.foo.serviceConfig.MemoryLimit = "512M";
Note however that overriding options in the original unit may not
work. For instance, you cannot override ExecStart.
It's also possible to customize instances of template units:
systemd.services."getty@tty4" =
{ baseUnit = "/etc/systemd/system/getty@.service";
serviceConfig.MemoryLimit = "512M";
};
This replaces the unit options linkTarget (which didn't allow
customisation) and extraConfig (which did allow customisation, but in
a non-standard way).
We used to have the configuration of the kernel available in a
somewhat convenient place (/run/booted-system/kernel-modules/config)
but that has disappeared. So instead just make /proc/configs.gz
available. It only eats a few kilobytes.
This is useful for packages like mosh, which use a wide UDP port range
by default for incoming connections.
Signed-off-by: Austin Seipp <aseipp@pobox.com>
We don't want to hardcode configuration options that the current kernel chose
for us when mounting the filesystem, since the defaults can change in the
future.
i18n.consoleKeyMap maps to KEYMAP=... in vconsole.conf and `loadkeymap'
in stage1. Both of these accept paths to a keymap file in addition to
a string containing the name of the keymap.
With this commit, it's possible to use your own keymap via:
i18n.consoleKeyMap = ./path/to/something.kmap
PostgreSQL defaults to having 'postgres' as the superuser. NixOS should
use this default name to provide a less surprising result to people who
enable services.postgres.
There are two fixes in this commit.
Firstly, I am creating proper symlinks for the Alias= definitions in the
.service files. This achieves the same result as `systemctl enable`, and
I think is preferred over `mv`.
Secondly, `networkmanager-init` now wants `NetworkManager.service`,
along with `ModemManager.service`. ModemManager does not depend on
NetworkManager (according to `systemctl list-dependencies ModemManager`),
thus NetworkManager never got started on boot.
It is parameterized by a function that takes a name and evaluates to the
option type for the attribute of that name. Together with
submoduleWithExtraArgs, this subsumes nixosSubmodule.
The mutableUsers feature uses `chpasswd` to set users passwords.
Passwords and their hashes were being piped into the program using
double quotes ("") to escape. This causes any `$` characters to be
expanded as shell variables. This is a serious problem because all the
password hash methods besides DES use multiple `$` in the hashes. Single
quotes ('') should be used instead to prevent shell variable expansion.
* Bump bumblebee to 3.2.1
* Remove config.patch - options it added can be passed to ./configure now
* Remove the provided xorg.conf
Provided xorg.conf was causing problems for some users,
and Bumblebee provides its own default configuration anyway.
* Make secondary X11 log to /var/log/X.bumblebee.log
* Add a module for bumblebee
Without this the HTML manual and manpage is quite unreadable (newlines
are squashed so it doesn't look like a list anymore).
(Unfortunately, this makes the source unreadable.)
Security-relevant changes:
* No (salted) passphrase hash send to the yubikey, only hash of the salt (as it was in the original implementation).
* Derive $k_luks with PBKDF2 from the yubikey $response (as the PBKDF2 salt) and the passphrase $k_user
(as the PBKDF2 password), so that if two-factor authentication is enabled
(a) a USB-MITM attack on the yubikey itself is not enough to break the system
(b) the potentially low-entropy $k_user is better protected against brute-force attacks
* Instead of using uuidgen, gather the salt (previously random uuid / uuid_r) directly from /dev/random.
* Length of the new salt in byte added as the parameter "saltLength", defaults to 16 byte.
Note: Length of the challenge is 64 byte, so saltLength > 64 may have no benefit over saltLengh = 64.
* Length of $k_luks derived with PBKDF2 in byte added as the parameter "keyLength", defaults to 64 byte.
Example: For a luks device with a 512-bit key, keyLength should be 64.
* Increase of the PBKDF2 iteration count per successful authentication added as the
parameter "iterationStep", defaults to 0.
Other changes:
* Add optional grace period before trying to find the yubikey, defaults to 2 seconds.
Full overview of the yubikey authentication process:
(1) Read $salt and $iterations from unencrypted device (UD).
(2) Calculate the $challenge from the $salt with a hash function.
Chosen instantiation: SHA-512($salt).
(3) Challenge the yubikey with the $challenge and receive the $response.
(4) Repeat three times:
(a) Prompt for the passphrase $k_user.
(b) Derive the key $k_luks for the luks device with a key derivation function from $k_user and $response.
Chosen instantiation: PBKDF2(HMAC-SHA-512, $k_user, $response, $iterations, keyLength).
(c) Try to open the luks device with $k_luks and escape loop (4) only on success.
(5) Proceed only if luks device was opened successfully, fail otherwise.
(6) Gather $new_salt from a cryptographically secure pseudorandom number generator
Chosen instantiation: /dev/random
(7) Calculate the $new_challenge from the $new_salt with the same hash function as (2).
(8) Challenge the yubikey with the $new_challenge and receive the $new_response.
(9) Derive the new key $new_k_luks for the luks device in the same manner as in (4) (b),
but with more iterations as given by iterationStep.
(10) Try to change the luks device's key $k_luks to $new_k_luks.
(11) If (10) was successful, write the $new_salt and the $new_iterations to the UD.
Note: $new_iterations = $iterations + iterationStep
Known (software) attack vectors:
* A MITM attack on the keyboard can recover $k_user. This, combined with a USB-MITM
attack on the yubikey for the $response (1) or the $new_response (2) will result in
(1) $k_luks being recovered,
(2) $new_k_luks being recovered.
* Any attacker with access to the RAM state of stage-1 at mid- or post-authentication
can recover $k_user, $k_luks, and $new_k_luks
* If an attacker has recovered $response or $new_response, he can perform a brute-force
attack on $k_user with it without the Yubikey needing to be present (using cryptsetup's
"luksOpen --verify-passphrase" oracle. He could even make a copy of the luks device's
luks header and run the brute-force attack without further access to the system.
* A USB-MITM attack on the yubikey will allow an attacker to attempt to brute-force
the yubikey's internal key ("shared secret") without it needing to be present anymore.
Credits:
* Florian Klien,
for the original concept and the reference implementation over at
https://github.com/flowolf/initramfs_ykfde
* Anthony Thysse,
for the reference implementation of accessing OpenSSL's PBKDF2 over at
http://www.ict.griffith.edu.au/anthony/software/pbkdf2.c
To be compatible with eb2f44c18c (Generate
/etc/passwd and /etc/group at build time). Without this you'll get this:
$ nixos-rebuild build
[...]
user-thrown exception: The option `users.extraGroups.unnamed-9.1.gid' is used but not defined.
Currently very basic gnome-shell launches on my laptop. Quite some
services won't start yet, most notable is gnome-control-center.
GTK3 apps still don't have theming applied and for example launching
chromium results in horrible red windows.
This is a rather large commit that switches user/group creation from using
useradd/groupadd on activation to just generating the contents of /etc/passwd
and /etc/group, and then on activation merging the generated files with the
files that exist in the system. This makes the user activation process much
cleaner, in my opinion.
The users.extraUsers.<user>.uid and users.extraGroups.<group>.gid must all be
properly defined (if <user>.createUser is true, which it is by default). My
pull request adds a lot of uids/gids to config.ids to solve this problem for
existing nixos services, but there might be configurations that break because
this change. However, this will be discovered during the build.
Option changes introduced by this commit:
* Remove the options <user>.isSystemUser and <user>.isAlias since
they don't make sense when generating /etc/passwd statically.
* Add <group>.members as a complement to <user>.extraGroups.
* Add <user>.passwordFile for setting a user's password from an encrypted
(shadow-style) file.
* Add users.mutableUsers which is true by default. This means you can keep
managing your users as previously, by using useradd/groupadd manually. This is
accomplished by merging the generated passwd/group file with the existing files
in /etc on system activation. The merging of the files is simplistic. It just
looks at the user/group names. If a user/group exists both on the system and
in the generated files, the system entry will be kept un-changed and the
generated entries will be ignored. The merging itself is performed with the
help of vipw/vigr to properly lock the account files during edit.
If mutableUsers is set to false, the generated passwd and group files will not
be merged with the system files on activation. Instead they will simply replace
the system files, and overwrite any changes done on the running system. The
same logic holds for user password, if the <user>.password or
<user>.passwordFile options are used. If mutableUsers is false, password will
simply be replaced on activation. If true, the initial user passwords will be
set according to the configuration, but existing passwords will not be touched.
I have tested this on a couple of different systems and it seems to work fine
so far. If you think this is a good idea, please test it. This way of adding
local users has been discussed in issue #103 (and this commit solves that
issue).
Rationale:
* The main reason for choosing to implement the PBA in accordance
with the Yubico documentation was to prevent a MITM-USB-attack
successfully recovering the new LUKS key.
* However, a MITM-USB-attacker can read user id and password when
they were entered for PBA, which allows him to recover the new
challenge after the PBA is complete, with which he can challenge
the Yubikey, decrypt the new AES blob and recover the LUKS key.
* Additionally, since the Yubikey shared secret is stored in the
same AES blob, after such an attack not only is the LUKS device
compromised, the Yubikey is as well, since the shared secret
has also been recovered by the attacker.
* Furthermore, with this method an attacker could also bruteforce
the AES blob, if he has access to the unencrypted device, which
would again compromise the Yubikey, should he be successful.
* Finally, with this method, once the LUKS key has been recovered
once, the encryption is permanently broken, while with the previous
system, the LUKS key itself it changed at every successful boot,
so recovering it once will not necessarily result in a permanent
breakage and will also not compromise the Yubikey itself (since
its secret is never stored anywhere but on the Yubikey itself).
Summary:
The current implementation opens up up vulnerability to brute-forcing
the AES blob, while retaining the current MITM-USB attack, additionally
making the consequences of this attack permanent and extending it to
the Yubikey itself.
switch-to-configuration.pl is currently hard-coded to assume that if a
unit is in the "auto-restart" state that something has gone wrong, but
this is not strictly true. For example, I run offlineimap as a oneshot
service restarting itself every minute (on success). NixOS currently
thinks that offlineimap has failed to start as it enters the
auto-restart state, because it doesn't consider why the unit failed.
This commit changes switch-to-configuration.pl to inspect the full
status of a unit in auto-restart state, and now only considers it failed
if the ExecMainStatus is non-zero.
Currently switch-to-configuration.pl uses system() calls to interact
with DBus. This can be error prone, especially when we are parsing
output that could change. In this commit, almost all calls to the
systemctl binary have been replaced with equivalent operations via DBus.