about summary refs log tree commit diff
path: root/nixpkgs/nixos
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2021-04-20 11:53:24 +0000
committerAlyssa Ross <hi@alyssa.is>2021-06-09 14:51:10 +0000
commit5c5963660bb5a35cb9e6ec6109765b4dbfd2e164 (patch)
tree0154b99cfcb5aa46c64c536a9b199b1f8880339d /nixpkgs/nixos
parentd42e9caa0c9dd28c1b0876cbefb5159df311ff63 (diff)
downloadnixlib-5c5963660bb5a35cb9e6ec6109765b4dbfd2e164.tar
nixlib-5c5963660bb5a35cb9e6ec6109765b4dbfd2e164.tar.gz
nixlib-5c5963660bb5a35cb9e6ec6109765b4dbfd2e164.tar.bz2
nixlib-5c5963660bb5a35cb9e6ec6109765b4dbfd2e164.tar.lz
nixlib-5c5963660bb5a35cb9e6ec6109765b4dbfd2e164.tar.xz
nixlib-5c5963660bb5a35cb9e6ec6109765b4dbfd2e164.tar.zst
nixlib-5c5963660bb5a35cb9e6ec6109765b4dbfd2e164.zip
nixos/users-groups: check format of passwd entries
Things will get quite broken if an /etc/passwd entry contains a
colon (which terminates a field), or a newline (which terminates a
record).  I know because I just accidentally made a user whose home
directory path contained a newline!

So let's make sure that can't happen.
Diffstat (limited to 'nixpkgs/nixos')
-rw-r--r--nixpkgs/nixos/modules/config/users-groups.nix22
1 files changed, 14 insertions, 8 deletions
diff --git a/nixpkgs/nixos/modules/config/users-groups.nix b/nixpkgs/nixos/modules/config/users-groups.nix
index 5ed1f568f499..9b2f37b212a8 100644
--- a/nixpkgs/nixos/modules/config/users-groups.nix
+++ b/nixpkgs/nixos/modules/config/users-groups.nix
@@ -6,6 +6,12 @@ let
   ids = config.ids;
   cfg = config.users;
 
+  isPasswdCompatible = str: !(hasInfix ":" str || hasInfix "\n" str);
+  passwdEntry = type: lib.types.addCheck type isPasswdCompatible // {
+    name = "passwdEntry ${type.name}";
+    description = "${type.description}, not containing newlines or colons";
+  };
+
   # Check whether a password hash will allow login.
   allowsLogin = hash:
     hash == "" # login without password
@@ -54,7 +60,7 @@ let
     options = {
 
       name = mkOption {
-        type = types.str;
+        type = passwdEntry types.str;
         apply = x: assert (builtins.stringLength x < 32 || abort "Username '${x}' is longer than 31 characters which is not allowed!"); x;
         description = ''
           The name of the user account. If undefined, the name of the
@@ -63,7 +69,7 @@ let
       };
 
       description = mkOption {
-        type = types.str;
+        type = passwdEntry types.str;
         default = "";
         example = "Alice Q. User";
         description = ''
@@ -124,7 +130,7 @@ let
       };
 
       home = mkOption {
-        type = types.path;
+        type = passwdEntry types.path;
         default = "/var/empty";
         description = "The user's home directory.";
       };
@@ -153,7 +159,7 @@ let
       };
 
       shell = mkOption {
-        type = types.nullOr (types.either types.shellPackage types.path);
+        type = types.nullOr (types.either types.shellPackage (passwdEntry types.path));
         default = pkgs.shadow;
         defaultText = "pkgs.shadow";
         example = literalExample "pkgs.bashInteractive";
@@ -213,7 +219,7 @@ let
       };
 
       hashedPassword = mkOption {
-        type = with types; nullOr str;
+        type = with types; nullOr (passwdEntry str);
         default = null;
         description = ''
           Specifies the hashed password for the user.
@@ -247,7 +253,7 @@ let
       };
 
       initialHashedPassword = mkOption {
-        type = with types; nullOr str;
+        type = with types; nullOr (passwdEntry str);
         default = null;
         description = ''
           Specifies the initial hashed password for the user, i.e. the
@@ -319,7 +325,7 @@ let
     options = {
 
       name = mkOption {
-        type = types.str;
+        type = passwdEntry types.str;
         description = ''
           The name of the group. If undefined, the name of the attribute set
           will be used.
@@ -336,7 +342,7 @@ let
       };
 
       members = mkOption {
-        type = with types; listOf str;
+        type = with types; listOf (passwdEntry str);
         default = [];
         description = ''
           The user names of the group members, added to the