Skip to content

Commit fcccfb9

Browse files
committed
nixos/pam/u2f: implement RFC0042
This module has a lot of options, so it's a good candidate for freeform settings.
1 parent da06c32 commit fcccfb9

File tree

3 files changed

+125
-89
lines changed

3 files changed

+125
-89
lines changed

nixos/doc/manual/release-notes/rl-2411.section.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@
197197
The derivation now installs "impl" headers selectively instead of by a wildcard.
198198
Use `imgui.src` if you just want to access the unpacked sources.
199199

200+
- `security.pam.u2f` now follows RFC42.
201+
All module options are now settable through the freeform `.settings`.
202+
200203
- Cinnamon has been updated to 6.2.
201204
- Following Mint 22 defaults, the Cinnamon module no longer ships geary and hexchat by default.
202205
- Nemo is now built with gtk-layer-shell support, note that for now it will be expected to see nemo-desktop

nixos/modules/security/pam.nix

Lines changed: 112 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ with lib;
77

88
let
99

10+
moduleSettingsType = with types; attrsOf (nullOr (oneOf [ bool str int pathInStore ]));
11+
moduleSettingsDescription = ''
12+
Boolean values render just the key if true, and nothing if false.
13+
Null values are ignored.
14+
All other values are rendered as key-value pairs.
15+
'';
16+
1017
mkRulesTypeOption = type: mkOption {
1118
# These options are experimental and subject to breaking changes without notice.
1219
description = ''
@@ -71,12 +78,12 @@ let
7178
'';
7279
};
7380
settings = mkOption {
74-
type = with types; attrsOf (nullOr (oneOf [ bool str int pathInStore ]));
81+
type = moduleSettingsType;
7582
default = {};
7683
description = ''
7784
Settings to add as `module-arguments`.
7885
79-
Boolean values render just the key if true, and nothing if false. Null values are ignored. All other values are rendered as key-value pairs.
86+
${moduleSettingsDescription}
8087
'';
8188
};
8289
};
@@ -660,11 +667,7 @@ let
660667
(let p11 = config.security.pam.p11; in { name = "p11"; enable = cfg.p11Auth; control = p11.control; modulePath = "${pkgs.pam_p11}/lib/security/pam_p11.so"; args = [
661668
"${pkgs.opensc}/lib/opensc-pkcs11.so"
662669
]; })
663-
(let u2f = config.security.pam.u2f; in { name = "u2f"; enable = cfg.u2fAuth; control = u2f.control; modulePath = "${pkgs.pam_u2f}/lib/security/pam_u2f.so"; settings = {
664-
inherit (u2f) debug interactive cue origin;
665-
authfile = u2f.authFile;
666-
appid = u2f.appId;
667-
}; })
670+
(let u2f = config.security.pam.u2f; in { name = "u2f"; enable = cfg.u2fAuth; control = u2f.control; modulePath = "${pkgs.pam_u2f}/lib/security/pam_u2f.so"; inherit (u2f) settings; })
668671
(let ussh = config.security.pam.ussh; in { name = "ussh"; enable = config.security.pam.ussh.enable && cfg.usshAuth; control = ussh.control; modulePath = "${pkgs.pam_ussh}/lib/security/pam_ussh.so"; settings = {
669672
ca_file = ussh.caFile;
670673
authorized_principals = ussh.authorizedPrincipals;
@@ -952,6 +955,12 @@ in
952955
imports = [
953956
(mkRenamedOptionModule [ "security" "pam" "enableU2F" ] [ "security" "pam" "u2f" "enable" ])
954957
(mkRenamedOptionModule [ "security" "pam" "enableSSHAgentAuth" ] [ "security" "pam" "sshAgentAuth" "enable" ])
958+
(mkRenamedOptionModule [ "security" "pam" "u2f" "authFile" ] [ "security" "pam" "u2f" "settings" "authfile" ])
959+
(mkRenamedOptionModule [ "security" "pam" "u2f" "appId" ] [ "security" "pam" "u2f" "settings" "appid" ])
960+
(mkRenamedOptionModule [ "security" "pam" "u2f" "origin" ] [ "security" "pam" "u2f" "settings" "origin" ])
961+
(mkRenamedOptionModule [ "security" "pam" "u2f" "debug" ] [ "security" "pam" "u2f" "settings" "debug" ])
962+
(mkRenamedOptionModule [ "security" "pam" "u2f" "interactive" ] [ "security" "pam" "u2f" "settings" "interactive" ])
963+
(mkRenamedOptionModule [ "security" "pam" "u2f" "cue" ] [ "security" "pam" "u2f" "settings" "cue" ])
955964
];
956965

957966
###### interface
@@ -1144,57 +1153,6 @@ in
11441153
'';
11451154
};
11461155

1147-
authFile = mkOption {
1148-
default = null;
1149-
type = with types; nullOr path;
1150-
description = ''
1151-
By default `pam-u2f` module reads the keys from
1152-
{file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or
1153-
{file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is
1154-
not set).
1155-
1156-
If you want to change auth file locations or centralize database (for
1157-
example use {file}`/etc/u2f-mappings`) you can set this
1158-
option.
1159-
1160-
File format is:
1161-
`username:first_keyHandle,first_public_key: second_keyHandle,second_public_key`
1162-
This file can be generated using {command}`pamu2fcfg` command.
1163-
1164-
More information can be found [here](https://developers.yubico.com/pam-u2f/).
1165-
'';
1166-
};
1167-
1168-
appId = mkOption {
1169-
default = null;
1170-
type = with types; nullOr str;
1171-
description = ''
1172-
By default `pam-u2f` module sets the application
1173-
ID to `pam://$HOSTNAME`.
1174-
1175-
When using {command}`pamu2fcfg`, you can specify your
1176-
application ID with the `-i` flag.
1177-
1178-
More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html)
1179-
'';
1180-
};
1181-
1182-
origin = mkOption {
1183-
default = null;
1184-
type = with types; nullOr str;
1185-
description = ''
1186-
By default `pam-u2f` module sets the origin
1187-
to `pam://$HOSTNAME`.
1188-
Setting origin to an host independent value will allow you to
1189-
reuse credentials across machines
1190-
1191-
When using {command}`pamu2fcfg`, you can specify your
1192-
application ID with the `-o` flag.
1193-
1194-
More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html)
1195-
'';
1196-
};
1197-
11981156
control = mkOption {
11991157
default = "sufficient";
12001158
type = types.enum [ "required" "requisite" "sufficient" "optional" ];
@@ -1209,33 +1167,104 @@ in
12091167
'';
12101168
};
12111169

1212-
debug = mkOption {
1213-
default = false;
1214-
type = types.bool;
1215-
description = ''
1216-
Debug output to stderr.
1217-
'';
1218-
};
1219-
1220-
interactive = mkOption {
1221-
default = false;
1222-
type = types.bool;
1223-
description = ''
1224-
Set to prompt a message and wait before testing the presence of a U2F device.
1225-
Recommended if your device doesn’t have a tactile trigger.
1226-
'';
1227-
};
1228-
1229-
cue = mkOption {
1230-
default = false;
1231-
type = types.bool;
1170+
settings = mkOption {
1171+
type = types.submodule {
1172+
freeformType = moduleSettingsType;
1173+
1174+
options = {
1175+
authfile = mkOption {
1176+
default = null;
1177+
type = with types; nullOr path;
1178+
description = ''
1179+
By default `pam-u2f` module reads the keys from
1180+
{file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or
1181+
{file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is
1182+
not set).
1183+
1184+
If you want to change auth file locations or centralize database (for
1185+
example use {file}`/etc/u2f-mappings`) you can set this
1186+
option.
1187+
1188+
File format is:
1189+
`username:first_keyHandle,first_public_key: second_keyHandle,second_public_key`
1190+
This file can be generated using {command}`pamu2fcfg` command.
1191+
1192+
More information can be found [here](https://developers.yubico.com/pam-u2f/).
1193+
'';
1194+
};
1195+
1196+
appid = mkOption {
1197+
default = null;
1198+
type = with types; nullOr str;
1199+
description = ''
1200+
By default `pam-u2f` module sets the application
1201+
ID to `pam://$HOSTNAME`.
1202+
1203+
When using {command}`pamu2fcfg`, you can specify your
1204+
application ID with the `-i` flag.
1205+
1206+
More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html)
1207+
'';
1208+
};
1209+
1210+
origin = mkOption {
1211+
default = null;
1212+
type = with types; nullOr str;
1213+
description = ''
1214+
By default `pam-u2f` module sets the origin
1215+
to `pam://$HOSTNAME`.
1216+
Setting origin to an host independent value will allow you to
1217+
reuse credentials across machines
1218+
1219+
When using {command}`pamu2fcfg`, you can specify your
1220+
application ID with the `-o` flag.
1221+
1222+
More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html)
1223+
'';
1224+
};
1225+
1226+
debug = mkOption {
1227+
default = false;
1228+
type = types.bool;
1229+
description = ''
1230+
Debug output to stderr.
1231+
'';
1232+
};
1233+
1234+
interactive = mkOption {
1235+
default = false;
1236+
type = types.bool;
1237+
description = ''
1238+
Set to prompt a message and wait before testing the presence of a U2F device.
1239+
Recommended if your device doesn’t have a tactile trigger.
1240+
'';
1241+
};
1242+
1243+
cue = mkOption {
1244+
default = false;
1245+
type = types.bool;
1246+
description = ''
1247+
By default `pam-u2f` module does not inform user
1248+
that he needs to use the u2f device, it just waits without a prompt.
1249+
1250+
If you set this option to `true`,
1251+
`cue` option is added to `pam-u2f`
1252+
module and reminder message will be displayed.
1253+
'';
1254+
};
1255+
};
1256+
};
1257+
default = { };
1258+
example = {
1259+
authfile = "/etc/u2f_keys";
1260+
authpending_file = "";
1261+
userpresence = 0;
1262+
pinverification = 1;
1263+
};
12321264
description = ''
1233-
By default `pam-u2f` module does not inform user
1234-
that he needs to use the u2f device, it just waits without a prompt.
1265+
Options to pass to the PAM module.
12351266
1236-
If you set this option to `true`,
1237-
`cue` option is added to `pam-u2f`
1238-
module and reminder message will be displayed.
1267+
${moduleSettingsDescription}
12391268
'';
12401269
};
12411270
};

nixos/tests/pam/pam-u2f.nix

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,24 @@ import ../make-test-python.nix ({ ... }:
77
{ ... }:
88
{
99
security.pam.u2f = {
10-
control = "required";
11-
cue = true;
12-
debug = true;
1310
enable = true;
14-
interactive = true;
15-
origin = "nixos-test";
11+
control = "required";
12+
settings = {
13+
cue = true;
14+
debug = true;
15+
interactive = true;
16+
origin = "nixos-test";
17+
# Freeform option
18+
userpresence = 1;
19+
};
1620
};
1721
};
1822

1923
testScript =
2024
''
2125
machine.wait_for_unit("multi-user.target")
2226
machine.succeed(
23-
'egrep "auth required .*/lib/security/pam_u2f.so.*cue.*debug.*interactive.*origin=nixos-test" /etc/pam.d/ -R'
27+
'egrep "auth required .*/lib/security/pam_u2f.so.*cue.*debug.*interactive.*origin=nixos-test.*userpresence=1" /etc/pam.d/ -R'
2428
)
2529
'';
2630
})

0 commit comments

Comments
 (0)