Open Izorkin opened 3 years ago
I marked this as stale due to inactivity. → More info
How to automatically load libnss_tcb.so.2
library from tcb
package. When run passwd
, library is only found in glibc package:
strace -ff passwd 2>&1 | grep libnss
openat(AT_FDCWD, "/nix/store/4nlgxhb09sdr51nc9hdm8az5b08vzkgx-glibc-2.35-163/lib/libnss_tcb.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
cc @Ma27 @lovesegfault @vcunat @mweinelt @trofi @ajs124 @Mic92
This link says: https://web.archive.org/web/20140923054517/http://felinemenace.org/~andrewg/configuring_gentoo_to_use_openwall_tcb/ it needs to be configured via nss modules and nscd would take care of loading it.
@Mic92 i have already set these parameters, already described in more detail here - https://github.com/openwall/tcb/issues/14
Draft patch:
diff --git a/nixos/modules/config/nsswitch.nix b/nixos/modules/config/nsswitch.nix
index b004072813b..8d7f87d3875 100644
--- a/nixos/modules/config/nsswitch.nix
+++ b/nixos/modules/config/nsswitch.nix
@@ -125,7 +125,7 @@ with lib;
system.nssDatabases = {
passwd = mkBefore [ "files" ];
group = mkBefore [ "files" ];
- shadow = mkBefore [ "files" ];
+ shadow = mkBefore (if config.security.tcb.enable then [ "tcb" ] else [ "files" ]);
hosts = mkMerge [
(mkOrder 998 [ "files" ])
(mkOrder 1499 [ "dns" ])
diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix
index af7fd4f712c..fd35a8350ae 100644
--- a/nixos/modules/module-list.nix
+++ b/nixos/modules/module-list.nix
@@ -280,6 +280,7 @@
./security/rtkit.nix
./security/sudo.nix
./security/systemd-confinement.nix
+ ./security/tcb.nix
./security/tpm2.nix
./security/wrappers/default.nix
./services/admin/meshcentral.nix
diff --git a/nixos/modules/programs/shadow.nix b/nixos/modules/programs/shadow.nix
index fab809f279a..bed7f286bdc 100644
--- a/nixos/modules/programs/shadow.nix
+++ b/nixos/modules/programs/shadow.nix
@@ -40,7 +40,10 @@ let
# users to change their account GECOS information.
# This should be made configurable.
#CHFN_RESTRICT frwh
-
+ '' + optionalString config.security.tcb.enable ''
+ USE_TCB yes
+ TCB_AUTH_GROUP yes
+ TCB_SYMLINKS NO
'';
mkSetuidRoot = source:
@@ -50,6 +53,13 @@ let
inherit source;
};
+ mkSetuidShadow = source:
+ { setgid = true;
+ owner = "root";
+ group = "shadow";
+ inherit source;
+ };
+
in
{
@@ -123,7 +133,10 @@ in
newgidmap = mkSetuidRoot "${pkgs.shadow.out}/bin/newgidmap";
} // lib.optionalAttrs config.users.mutableUsers {
chsh = mkSetuidRoot "${pkgs.shadow.out}/bin/chsh";
+ } // lib.optionalAttrs (config.users.mutableUsers && (!config.security.tcb.enable)) {
passwd = mkSetuidRoot "${pkgs.shadow.out}/bin/passwd";
+ } // lib.optionalAttrs (config.users.mutableUsers && config.security.tcb.enable) {
+ passwd = mkSetuidShadow "${pkgs.shadow.out}/bin/passwd";
};
};
}
diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix
index 273bc796341..2d0efe689ce 100644
--- a/nixos/modules/security/pam.nix
+++ b/nixos/modules/security/pam.nix
@@ -491,8 +491,15 @@ let
# The required pam_unix.so module has to come after all the sufficient modules
# because otherwise, the account lookup will fail if the user does not exist
# locally, for example with MySQL- or LDAP-auth.
+ optionalString (!config.security.tcb.enable)
''
account required pam_unix.so
+ '' +
+ optionalString config.security.tcb.enable
+ ''
+ account required ${pkgs.tcb}/lib/security/pam_tcb.so shadow fork helper=/run/wrappers/bin/tcb_chkpwd audit debug
+ '' +
+ ''
# Authentication management.
'' +
@@ -584,9 +591,12 @@ let
auth required ${pkgs.duo-unix}/lib/security/pam_duo.so
''
)) +
- optionalString cfg.unixAuth ''
+ optionalString (cfg.unixAuth && (!config.security.tcb.enable)) ''
auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth try_first_pass
'' +
+ optionalString (cfg.unixAuth && config.security.tcb.enable) ''
+ auth sufficient ${pkgs.tcb}/lib/security/pam_tcb.so nullok shadow fork helper=/run/wrappers/bin/tcb_chkpwd audit debug
+ '' +
optionalString cfg.otpwAuth ''
auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so
'' +
@@ -605,8 +615,15 @@ let
auth required pam_deny.so
# Password management.
+ '' +
+ optionalString (!config.security.tcb.enable)
+ ''
password sufficient pam_unix.so nullok sha512
'' +
+ optionalString config.security.tcb.enable
+ ''
+ password sufficient ${pkgs.tcb}/lib/security/pam_tcb.so shadow fork nullok write_to=tcb helper=/run/wrappers/bin/tcb_chkpwd audit debug
+ '' +
optionalString config.security.pam.enableEcryptfs ''
password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so
'' +
@@ -638,9 +655,14 @@ let
optionalString cfg.setEnvironment ''
session required pam_env.so conffile=/etc/pam/environment readenv=0
'' +
+ optionalString (!config.security.tcb.enable)
''
session required pam_unix.so
'' +
+ optionalString config.security.tcb.enable
+ ''
+ session required ${pkgs.tcb}/lib/security/pam_tcb.so helper=/run/wrappers/bin/tcb_chkpwd audit debug
+ '' +
optionalString cfg.setLoginUid ''
session ${if config.boot.isContainer then "optional" else "required"} pam_loginuid.so
'' +
@@ -1236,7 +1258,7 @@ in
boot.supportedFilesystems = optionals config.security.pam.enableEcryptfs [ "ecryptfs" ];
- security.wrappers = {
+ security.wrappers = mkIf (!config.security.tcb.enable) {
unix_chkpwd = {
setuid = true;
owner = "root";
diff --git a/nixos/modules/security/tcb.nix b/nixos/modules/security/tcb.nix
new file mode 100644
index 00000000000..1c1b550f417
--- /dev/null
+++ b/nixos/modules/security/tcb.nix
@@ -0,0 +1,26 @@
+{ lib, config, pkgs, ... }:
+let
+ cfg = config.security.tcb;
+
+in {
+ meta = {
+ maintainers = [ lib.maintainers.izorkin ];
+ };
+
+ options.security.tcb = {
+ enable = lib.mkEnableOption (lib.mdDoc "Alternative shadow scheme");
+ };
+
+ config = lib.mkIf cfg.enable {
+ environment.systemPackages = [ pkgs.tcb.bin pkgs.tcb.out ];
+
+ security.wrappers = {
+ tcb_chkpwd = {
+ setgid = true;
+ owner = "root";
+ group = "shadow";
+ source = "${pkgs.tcb}/libexec/chkpwd/tcb_chkpwd";
+ };
+ };
+ };
+}
diff --git a/nixos/tests/shadow.nix b/nixos/tests/shadow.nix
index baa2e5945c0..eae52fb9646 100644
--- a/nixos/tests/shadow.nix
+++ b/nixos/tests/shadow.nix
@@ -12,6 +12,8 @@ in import ./make-test-python.nix ({ pkgs, ... }: {
nodes.shadow = { pkgs, ... }: {
environment.systemPackages = [ pkgs.shadow ];
+ security.tcb.enable = true;
+
users = {
mutableUsers = true;
users.emma = {
@@ -45,6 +47,7 @@ in import ./make-test-python.nix ({ pkgs, ... }: {
testScript = ''
shadow.wait_for_unit("multi-user.target")
shadow.wait_until_succeeds("pgrep -f 'agetty.*tty1'")
+ shadow.wait_until_succeeds("tcb_convert")
with subtest("Normal login"):
shadow.send_key("alt-f2")
diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix
index 61d70ccc19b..102460cf6f9 100644
--- a/nixos/modules/config/users-groups.nix
+++ b/nixos/modules/config/users-groups.nix
@@ -579,6 +579,9 @@ in {
render.gid = ids.gids.render;
sgx.gid = ids.gids.sgx;
shadow.gid = ids.gids.shadow;
+ auth.gid = ids.gids.auth;
+ chkpwd.gid = ids.gids.chkpwd;
+ sys.gid = ids.gids.sys;
};
system.activationScripts.users = {
diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix
index 17ea04cb4ec..08aeca76734 100644
--- a/nixos/modules/misc/ids.nix
+++ b/nixos/modules/misc/ids.nix
@@ -356,6 +356,9 @@ in
rstudio-server = 324;
localtimed = 325;
automatic-timezoned = 326;
+ # auth = 327; # unused
+ # chkpwd = 328; # unused
+ # sys = 329; # unused
# When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399!
@@ -666,6 +669,9 @@ in
rstudio-server = 324;
localtimed = 325;
automatic-timezoned = 326;
+ auth = 327;
+ chkpwd = 328;
+ sys = 329;
# When adding a gid, make sure it doesn't match an existing
# uid. Users and groups with the same name should have equal
And in shadow
package, need to activate parameter --enable-tcb
.
Allow this variant?
diff --git a/pkgs/development/libraries/glibc/default.nix b/pkgs/development/libraries/glibc/default.nix
index 791ac47536f..95a7fcbac2b 100644
--- a/pkgs/development/libraries/glibc/default.nix
+++ b/pkgs/development/libraries/glibc/default.nix
@@ -149,6 +149,7 @@ callPackage ./common.nix { inherit stdenv; } {
# Work around a Nix bug: hard links across outputs cause a build failure.
cp $bin/bin/getconf $bin/bin/getconf_
mv $bin/bin/getconf_ $bin/bin/getconf
+ ln -sf /run/current-system/sw/lib/libnss_tcb.so.2 $out/lib/libnss_tcb.so.2
'';
separateDebugInfo = true;
As expressed in https://github.com/NixOS/nixpkgs/pull/207547#issuecomment-1364590045, adding the NSS module to LD_LIBRARY_PATH to get glibc to load it into every process is the wrong approach, and NSS lookups via should ns(n)cd most likely should work.
I asked for confirmation in https://github.com/openwall/tcb/issues/14#issuecomment-1364590368.
As for the draft patch, we should probably see how we can use/extend the existing module options to be able to express this, so this can be properly tested in a VM test.
@flokli right now I don't know how to automatically create shadow
files in /etc/tcb/${users}/
directorys. without using intermediate step of converting the file /etc/shadow
to /etc/tcb/${users}/shadow
using the tcb_convert
utility.
The suggested build flag didn't help either:
diff --git a/pkgs/tools/security/tcb/default.nix b/pkgs/tools/security/tcb/default.nix
index 63b252be952..35de1dc9ea8 100644
--- a/pkgs/tools/security/tcb/default.nix
+++ b/pkgs/tools/security/tcb/default.nix
@@ -28,6 +28,10 @@ stdenv.mkDerivation rec {
--replace "INCLUDEDIR = \$(PREFIX)/include" "INCLUDEDIR = $dev/include"
'';
+ CFLAGS = [
+ "-DENABLE_SETFSUGID"
+ ];
+
meta = with lib; {
description = "Alternative password shadowing scheme";
longDescription = ''
systemctl cat nscd | grep LD_LIBRARY_PATH
Environment="LD_LIBRARY_PATH=/nix/store/07ccvqbj89943b0vwcmqzd9la7jfzka0-systemd-252.1/lib:/nix/store/jci59xwz7pkj4rysn17sjsqzdgkqmvnf-tcb-1.2/lib"
Library libnss_tcb.so.2 not found.
To test, I have changed to other nss module:
shadow: systemd
strace -ff passwd 2>&1 | grep libnss
[pid 4189] openat(AT_FDCWD, "/nix/store/ayfr5l52xkqqjn3n4h9jfacgnchz1z7s-glibc-2.35-224/lib/libnss_systemd.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/nix/store/ayfr5l52xkqqjn3n4h9jfacgnchz1z7s-glibc-2.35-224/lib/libnss_systemd.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
NSCD does not find an existing nss library.
ls -lah /nix/store/07ccvqbj89943b0vwcmqzd9la7jfzka0-systemd-252.1/lib | grep libnss_systemd
-r-xr-xr-x 1 root root 434K Jan 1 1970 libnss_systemd.so.2
Most likely the problem is not with tcb.
Can you convert your test case to a proper VM test? There is a nscd test in nixpkgs, and this stuff usually should work.
It looks like there's no request type in nscd protocol to ask for shadow database entries.
Is the passwd database not sufficient?
Can you convert your test case to a proper VM test?
I'll try to think of something with the dough. The required changes have not yet been added to the master branch.
Is the passwd database not sufficient?
TCB manages only the shadow files, which are placed in the /etc/shadow/${username}
directory.
Can you convert your test case to a proper VM test? There is a nscd test in nixpkgs, and this stuff usually should work.
Updated draft patch - https://github.com/NixOS/nixpkgs/issues/109457#issuecomment-1339020749
Modified the shadow
test and using this glibc
patch:
diff --git a/pkgs/development/libraries/glibc/default.nix b/pkgs/development/libraries/glibc/default.nix
index 791ac47536f..3e581d2967b 100644
--- a/pkgs/development/libraries/glibc/default.nix
+++ b/pkgs/development/libraries/glibc/default.nix
@@ -149,6 +149,9 @@ callPackage ./common.nix { inherit stdenv; } {
# Work around a Nix bug: hard links across outputs cause a build failure.
cp $bin/bin/getconf $bin/bin/getconf_
mv $bin/bin/getconf_ $bin/bin/getconf
+ # Allow load libnss tcb module.
+ # It is currently not possible to load third party libnss modules from a custom directory.
+ ln -sf /run/current-system/sw/lib/libnss_tcb.so.2 $out/lib/libnss_tcb.so.2
'';
@flokli rechecking with system.nssModules
- not working:
diff --git a/nixos/modules/security/tcb.nix b/nixos/modules/security/tcb.nix
index 1c1b550f417..8e28ac5da22 100644
--- a/nixos/modules/security/tcb.nix
+++ b/nixos/modules/security/tcb.nix
@@ -12,7 +12,9 @@ in {
};
config = lib.mkIf cfg.enable {
- environment.systemPackages = [ pkgs.tcb.bin pkgs.tcb.out ];
+ environment.systemPackages = [ pkgs.tcb.bin ];
+
+ system.nssModules = [ pkgs.tcb.out ];
security.wrappers = {
tcb_chkpwd = {
Need to find a way to load the libnss module.
Debug with LD_DEBUG
:
LD_DEBUG=all passwd
...
224612: file=libnss_tcb.so.2 [0]; dynamically loaded by /nix/store/1xczacg4m01bgcqhdkh11b96cdbhim5l-glibc-2.35-224/lib/libc.so.6 [0]
224612: find library=libnss_tcb.so.2 [0]; searching
224612: search cache=/nix/store/1xczacg4m01bgcqhdkh11b96cdbhim5l-glibc-2.35-224/etc/ld.so.cache
224612: search path=/nix/store/1xczacg4m01bgcqhdkh11b96cdbhim5l-glibc-2.35-224/lib (system search path)
224612: trying file=/nix/store/1xczacg4m01bgcqhdkh11b96cdbhim5l-glibc-2.35-224/lib/libnss_tcb.so.2
224612:
224611:
224611: file=libnss_tcb.so.2 [0]; dynamically loaded by /nix/store/1xczacg4m01bgcqhdkh11b96cdbhim5l-glibc-2.35-224/lib/libc.so.6 [0]
224611: find library=libnss_tcb.so.2 [0]; searching
224611: search cache=/nix/store/1xczacg4m01bgcqhdkh11b96cdbhim5l-glibc-2.35-224/etc/ld.so.cache
224611: search path=/nix/store/1xczacg4m01bgcqhdkh11b96cdbhim5l-glibc-2.35-224/lib (system search path)
224611: trying file=/nix/store/1xczacg4m01bgcqhdkh11b96cdbhim5l-glibc-2.35-224/lib/libnss_tcb.so.2
224611:
passwd: Permission denied
passwd: пароль не изменён
...
Debug with
LD_DEBUG
You cannot fully do that. Please note that LD_*
environment variables are not supposed to fully work, if at all, nor to have no side-effects, when used on SUID/SGID programs. So when you enable LD_DEBUG
, it may either be ignored or result in the binary running as non-SUID/SGID (and likely failing to work correctly for that reason). In this example, you can probably use LD_DEBUG=all
on a copy of passwd
that is not SUID/SGID and run the command as root, thus testing its ability to change passwords when run by root. However, you cannot really do that as non-root, thus cannot see what really happens when you're changing a non-root user's password when the command is run by the user.
I was able to load the libnss_tcb library via /etc/ld.so.cache. On a normal user, changing the password and logging in also works.
It does not want to work through the LD_LIBRARY_PATH=/nix/store/s6w6az734vw7n9fzb51a9adr0xfxlhw6-tcb-1.2/lib
variable.
how to automatically create
shadow
files in/etc/tcb/${users}/
directorys. without using intermediate step of converting the file/etc/shadow
to/etc/tcb/${users}/shadow
using thetcb_convert
utility.
It's fine to have the intermediate step - with that, you can treat tcb_convert
as your tool to create the files. No reason to reimplement functionality that we already have due to tcb_convert
. Here's how we do it in Owl's owl-etc
package, where the system normally uses tcb
right upon installation (due to this logic):
%triggerin -- shadow-utils
function pause()
{
echo
echo "Install will continue in 10 seconds..."
sleep 10
}
# Determine whether the current /etc/shadow matches the initial version
# as provided by this package.
if [ -e /etc/shadow.rpmnew -o ! -e /etc/shadow ]; then
SHADOW_INITIAL=no
elif [ "`sha1sum < /etc/shadow`" = "%shadow_initial_sha1 -" ]; then
SHADOW_INITIAL=yes
else
SHADOW_INITIAL=no
fi
# New install?
if [ $SHADOW_INITIAL = yes -a ! -e /etc/tcb -a \
! -e /etc/nsswitch.conf.rpmnew ]; then
echo "No existing password shadowing found, will use /etc/tcb."
/sbin/tcb_convert && rm /etc/shadow
# Updating an install that uses tcb?
elif [ \( $SHADOW_INITIAL = yes -o ! -e /etc/shadow \) -a -d /etc/tcb ]; then
echo "OK, already using /etc/tcb."
rm -f /etc/shadow
# Updating an install that uses shadow?
elif [ $SHADOW_INITIAL = no -a -f /etc/shadow -a ! -e /etc/tcb ]; then
if [ -e /etc/nsswitch.conf.rpmnew ]; then
cat << EOF
This system appears to be using /etc/shadow. Conversion to /etc/tcb
is desired, but /etc/nsswitch.conf appears to have been modified locally
preventing automatic conversion. You'll need to either convert this
system to /etc/tcb manually or knowingly keep it with /etc/shadow
(which is also non-default with a number of other configuration files).
Please refer to tcb_convert(8) for instructions.
EOF
else
cat << EOF
This system appears to be using /etc/shadow and will now be converted
to /etc/tcb.
EOF
if /sbin/tcb_convert; then
echo "tcb_convert succeeded"
if [ "`%_sbindir/control passwd`" != restricted ]; then
echo "Setting passwd(1) file modes for tcb"
%_sbindir/control passwd tcb
ls -l %_bindir/passwd
fi
rm -f /etc/shadow.rpmnew
mv -v /etc/shadow /etc/shadow-pre-tcb
chmod -v go-rwx /etc/shadow*
cat << EOF
The old shadow file and any its backups have been left around - be sure
to remove them once you're positive the conversion has succeeded.
EOF
else
cat << EOF
tcb_convert FAILED
Your system may be in an inconsistent state now, please perform the
conversion to /etc/tcb manually. See tcb_convert(8) for instructions.
EOF
fi
fi
pause
# Updating a misconfigured install?
elif [ $SHADOW_INITIAL = no -a -e /etc/shadow -a -e /etc/tcb ]; then
cat << EOF
This system appears to be misconfigured: both /etc/shadow and /etc/tcb
exist. It may be in an inconsistent state now, please complete the
conversion to /etc/tcb manually. See tcb_convert(8) for instructions.
EOF
pause
# Possible other misconfigurations.
else
cat << EOF
This system's local user authentication appears to be misconfigured.
You might need to convert it to /etc/tcb manually, see tcb_convert(8)
for instructions.
EOF
pause
fi
rm -f /etc/{passwd,shadow,group}.rpmnew
It does not want to work through the
LD_LIBRARY_PATH=/nix/store/s6w6az734vw7n9fzb51a9adr0xfxlhw6-tcb-1.2/lib
variable.
Indeed. This is not supposed to work for the same reason I just described. Edit: BTW, I told you so in https://github.com/openwall/tcb/issues/14#issuecomment-1338036737
Is there a patch to add tcb support directly to glibc?
Is there a patch to add tcb support directly to glibc?
Not that I'm aware of. However, musl has it.
Project description The tcb package contains core components of our tcb suite implementing the alternative password shadowing scheme on Owl.
More information:
I could only do the tcb package - https://github.com/NixOS/nixpkgs/compare/master...Izorkin:shadow-tcb Need add patch to shadow-utils - https://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/shadow-utils/ and integrate to
/etc/pam.d/system-auth
and/etc/nsswitch.conf