* Make the generation of /etc/pam.d more declarative. There now is an

option security.pam.services containing the list of PAM services.
  For instance, the SLiM module simply declares:

    security.pam.services = [ { name = "slim"; localLogin = true; } ];

svn path=/nixos/trunk/; revision=16729
This commit is contained in:
Eelco Dolstra 2009-08-16 14:49:14 +00:00
parent 88c505c9e0
commit 39bffdb34c
26 changed files with 477 additions and 571 deletions

View File

@ -1,5 +0,0 @@
auth sufficient pam_rootok.so
auth required pam_permit.so
account required pam_permit.so
password required pam_permit.so
session required pam_permit.so

View File

@ -1,13 +0,0 @@
@isLDAPEnabled@ auth sufficient @pam_ldap@/lib/security/pam_ldap.so
auth sufficient @pam_unix2@/lib/security/pam_unix2.so
auth required pam_deny.so
@isLDAPEnabled@ account optional @pam_ldap@/lib/security/pam_ldap.so
account required @pam_unix2@/lib/security/pam_unix2.so
@isLDAPEnabled@ password sufficient @pam_ldap@/lib/security/pam_ldap.so
password requisite @pam_unix2@/lib/security/pam_unix2.so nullok
@syncSambaPasswords@
@isLDAPEnabled@ session optional @pam_ldap@/lib/security/pam_ldap.so
session required @pam_unix2@/lib/security/pam_unix2.so

View File

@ -1 +0,0 @@
session optional @pam_console@/lib/security/pam_console.so debug handlersfile=@pamConsoleHandlers@

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,5 +0,0 @@
auth include common
account include common
password include common
session include common
session include common-console

View File

@ -1,5 +0,0 @@
auth include common
account include common
password include common
session include common
session include common-console

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,8 +0,0 @@
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

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,6 +0,0 @@
# Used by groupadd etc.
auth sufficient pam_rootok.so
auth required pam_permit.so
account required pam_permit.so
password required pam_permit.so
session required pam_deny.so

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,6 +0,0 @@
auth sufficient pam_rootok.so
auth include common
account include common
password include common
session include common
session optional pam_xauth.so xauthpath=@xauth@/bin/xauth systemuser=99

View File

@ -1,5 +0,0 @@
auth sufficient pam_rootok.so
auth required pam_permit.so
account required pam_permit.so
password required pam_permit.so
session required pam_permit.so

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -3,8 +3,12 @@
{config, pkgs, ...}: {config, pkgs, ...}:
with pkgs.lib;
let let
inherit (pkgs) pam_unix2 pam_console pam_ldap;
# !!! ugh, these files shouldn't be created here. # !!! ugh, these files shouldn't be created here.
pamConsoleHandlers = pkgs.writeText "console.handlers" '' pamConsoleHandlers = pkgs.writeText "console.handlers" ''
console consoledevs /dev/tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9] console consoledevs /dev/tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9]
@ -14,45 +18,122 @@ let
pamConsolePerms = ./console.perms; pamConsolePerms = ./console.perms;
generatePAMConfig = program: makePAMService =
let isLDAPEnabled = config.users.ldap.enable; in { name
{ source = pkgs.substituteAll { , # If set, root doesn't need to authenticate (e.g. for the "chsh"
src = ./pam.d + ("/" + program); # service).
inherit (pkgs) pam_unix2 pam_console; rootOK ? false
pam_ldap = , # If set, this is a local login (e.g. virtual console or X), so
if isLDAPEnabled # the user gets ownership of audio devices etc.
then pkgs.pam_ldap localLogin ? false
else "/no-such-path"; , # Whether to forward XAuth keys between users. Mostly useful
inherit (pkgs.xorg) xauth; # for "su".
inherit pamConsoleHandlers; forwardXAuth ? false
isLDAPEnabled = if isLDAPEnabled then "" else "#"; }:
syncSambaPasswords = if config.services.samba.syncPasswordsByPam
then "password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass" { source = pkgs.writeText "${name}.pam"
else "# change samba configuration options to make passwd sync the samba auth database as well here.."; # !!! TODO: move the LDAP stuff to the LDAP module, and the
}; # Samba stuff to the Samba module. This requires that the PAM
target = "pam.d/" + program; # module provides the right hooks.
''
# Account management.
${optionalString config.users.ldap.enable
"account optional ${pam_ldap}/lib/security/pam_ldap.so"}
account required ${pam_unix2}/lib/security/pam_unix2.so
# Authentication management.
${optionalString rootOK
"auth sufficient pam_rootok.so"}
${optionalString config.users.ldap.enable
"auth sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
auth sufficient ${pam_unix2}/lib/security/pam_unix2.so
auth required pam_deny.so
# Password management.
${optionalString config.users.ldap.enable
"password sufficient ${pam_ldap}/lib/security/pam_ldap.so"}
password requisite ${pam_unix2}/lib/security/pam_unix2.so nullok
${optionalString config.services.samba.syncPasswordsByPam
"password optional ${pkgs.samba}/lib/security/pam_smbpass.so nullok use_authtok try_first_pass"}
# Session management.
${optionalString config.users.ldap.enable
"session optional ${pam_ldap}/lib/security/pam_ldap.so"}
session required ${pam_unix2}/lib/security/pam_unix2.so
${optionalString localLogin
"session optional ${pam_console}/lib/security/pam_console.so debug handlersfile=${pamConsoleHandlers}"}
${optionalString forwardXAuth
"session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99"}
'';
target = "pam.d/${name}";
}; };
in in
{ {
environment.etc = map generatePAMConfig
[ "login" ###### interface
"su"
"other" options = {
"passwd"
"shadow" security.pam.services = mkOption {
"sshd" default = [];
"lshd" example = [ { name = "chsh"; rootOK = true; } ];
"useradd" description =
"chsh" ''
"xlock" This option defines the PAM services. A service typically
"samba" corresponds to a program that uses PAM,
"cups" e.g. <command>login</command> or <command>passwd</command>.
"ftp" Each element of this list is an attribute set describing a
"ejabberd" service. The attribute <varname>name</varname> specifies
"kde" the name of the service. The attribute
"common" <varname>rootOK</varname> specifies whether the root user is
"common-console" # shared stuff for interactive local sessions allowed to use this service without authentication. The
attribute <varname>localLogin</varname> specifies whether
this is a local login service (e.g. <command>xdm</command>),
which implies that the user gets 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>).
'';
};
};
###### implementation
config = {
environment.systemPackages =
# Include the PAM modules in the system path mostly for the manpages.
[ pkgs.pam pam_unix2 ]
++ optional config.users.ldap.enable pam_ldap;
environment.etc = map makePAMService config.security.pam.services;
security.pam.services =
# Most of these should be moved to specific modules.
[ { name = "cups"; }
{ name = "ejabberd"; }
{ name = "ftp"; }
{ name = "lshd"; }
{ name = "passwd"; }
{ name = "samba"; }
{ name = "sshd"; }
{ name = "xlock"; }
{ name = "chsh"; rootOK = true; }
{ name = "su"; rootOK = true; forwardXAuth = true; }
# Note: useradd, groupadd etc. aren't setuid root, so it
# doesn't really matter what the PAM config says as long as it
# lets root in.
{ name = "useradd"; rootOK = true; }
# Used by groupadd etc.
{ name = "shadow"; rootOK = true; }
{ name = "login"; localLogin = true; }
]; ];
};
} }

View File

@ -1,79 +1,65 @@
{pkgs, config, ...}: {pkgs, config, ...}:
###### interface with pkgs.lib;
let let
inherit (pkgs.lib) mkOption;
cfg = config.security.sudo;
inherit (pkgs) sudo;
in
{
###### interface
options = { options = {
security = {
sudo = {
enable = mkOption { security.sudo.enable = mkOption {
default = true; default = true;
description = " description =
''
Whether to enable the <command>sudo</command> command, which Whether to enable the <command>sudo</command> command, which
allows non-root users to execute commands as root. allows non-root users to execute commands as root.
"; '';
}; };
configFile = mkOption { security.sudo.configFile = mkOption {
default = " # Note: if syntax errors are detected in this file, the NixOS
# WARNING: do not edit this file directly or with \"visudo\". Instead, # configuration will fail to build.
default =
''
# WARNING: do not edit this file directly or with "visudo". Instead,
# edit the source file in /etc/nixos/nixos/etc/sudoers. # edit the source file in /etc/nixos/nixos/etc/sudoers.
# \"root\" is allowed to do anything. # "root" is allowed to do anything.
root ALL=(ALL) SETENV: ALL root ALL=(ALL) SETENV: ALL
# Users in the \"wheel\" group can do anything. # Users in the "wheel" group can do anything.
%wheel ALL=(ALL) SETENV: ALL %wheel ALL=(ALL) SETENV: ALL
"; '';
description = " description =
''
This string contains the contents of the This string contains the contents of the
<filename>sudoers</filename> file. <filename>sudoers</filename> file.
"; '';
# If syntax errors are detected in this file, the NixOS };
# configuration will fail to build.
}; };
};
};
};
in
###### implementation ###### implementation
let
cfg = config.security.sudo;
inherit (pkgs.lib) mkIf;
inherit (pkgs) sudo;
in
mkIf cfg.enable { config = mkIf cfg.enable {
require = [
options
# config.environment.etc security.extraSetuidPrograms = [ "sudo" ];
# ../etc/default.nix
# ? # config.environment.extraPackages environment.systemPackages = [ sudo ];
# ? # config.security.extraSetuidPrograms
];
security = { security.pam.services = [ { name = "sudo"; } ];
extraSetuidPrograms = [
"sudo"
];
};
environment = { environment.etc = singleton
extraPackages = [ sudo ]; { source = pkgs.runCommand "sudoers"
etc = [
{
source = ./sudo.pam;
target = "pam.d/sudo";
}
{
source = pkgs.runCommand "sudoers"
{ src = pkgs.writeText "sudoers-in" cfg.configFile; } { src = pkgs.writeText "sudoers-in" cfg.configFile; }
# Make sure that the sudoers file is syntactically valid. # Make sure that the sudoers file is syntactically valid.
# (currently disabled - NIXOS-66) # (currently disabled - NIXOS-66)
@ -81,7 +67,8 @@ mkIf cfg.enable {
"cp $src $out"; "cp $src $out";
target = "sudoers"; target = "sudoers";
mode = "0440"; mode = "0440";
}
];
}; };
};
} }

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,44 +1,6 @@
{pkgs, config, ...}: {pkgs, config, ...}:
###### interface with pkgs.lib;
let
inherit (pkgs.lib) mkOption mkIf;
options = {
services = {
dovecot = {
enable = mkOption {
default = false;
description = "Whether to enable dovecot POP3/IMAP server.";
};
user = mkOption {
default = "dovecot";
description = "dovecot user name";
};
group = mkOption {
default = "dovecot";
description = "dovecot group name";
};
sslServerCert = mkOption {
default = "";
description = "Server certificate";
};
sslCACert = mkOption {
default = "";
description = "CA certificate used by server certificate";
};
sslServerKey = mkOption {
default = "";
description = "Server key";
};
};
};
};
in
###### implementation
let let
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces"; startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
@ -61,7 +23,6 @@ let
disable_plaintext_auth = no disable_plaintext_auth = no
'') '')
+ '' + ''
login_user = ${cfg.user} login_user = ${cfg.user}
login_chroot = no login_chroot = no
@ -84,48 +45,78 @@ let
pop3_uidl_format = %08Xv%08Xu pop3_uidl_format = %08Xv%08Xu
log_path = /var/log/dovecot.log log_path = /var/log/dovecot.log
''
;
confFile = pkgs.writeText "dovecot.conf" dovecotConf;
pamdFile = pkgs.writeText "dovecot.pam" ''
auth include common
account include common
''; '';
confFile = pkgs.writeText "dovecot.conf" dovecotConf;
in in
mkIf config.services.dovecot.enable { {
require = [ ###### interface
options
];
environment = { options = {
etc = [{
source = pamdFile; services.dovecot = {
target = "pam.d/dovecot";
}]; enable = mkOption {
default = false;
description = "Whether to enable the Dovecot POP3/IMAP server.";
}; };
users = { user = mkOption {
extraUsers = [{ default = "dovecot";
name = cfg.user; description = "Dovecot user name.";
};
group = mkOption {
default = "dovecot";
description = "Dovecot group name.";
};
sslServerCert = mkOption {
default = "";
description = "Server certificate";
};
sslCACert = mkOption {
default = "";
description = "CA certificate used by the server certificate.";
};
sslServerKey = mkOption {
default = "";
description = "Server key.";
};
};
};
###### implementation
config = mkIf config.services.dovecot.enable {
security.pam.services = [ { name = "dovecot"; } ];
users.extraUsers = singleton
{ name = cfg.user;
uid = config.ids.uids.dovecot; uid = config.ids.uids.dovecot;
description = "Dovecot user"; description = "Dovecot user";
group = cfg.group; group = cfg.group;
}];
extraGroups = [{
name = cfg.group;
gid = config.ids.gids.dovecot;
}];
}; };
services = { users.extraGroups = singleton
extraJobs = [{ { name = cfg.group;
name = "dovecot"; gid = config.ids.gids.dovecot;
};
job = '' services.extraJobs = singleton
{ name = "dovecot";
job =
''
description "Dovecot IMAP/POP3 server" description "Dovecot IMAP/POP3 server"
start on ${startingDependency}/started start on ${startingDependency}/started
@ -138,7 +129,8 @@ mkIf config.services.dovecot.enable {
respawn ${pkgs.dovecot}/sbin/dovecot -F -c ${confFile} respawn ${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}
''; '';
}];
}; };
};
} }

View File

@ -1,53 +1,15 @@
{pkgs, config, ...}: {pkgs, config, ...}:
###### interface with pkgs.lib;
let let
inherit (pkgs.lib) mkOption;
options = {
services = {
atd = {
enable = mkOption {
default = true;
description = ''
Whether to enable the `at' daemon, a command scheduler.
'';
};
allowEveryone = mkOption {
default = false;
description = ''
Whether to make /var/spool/at{jobs,spool} writeable
by everyone (and sticky). This is normally not needed since
the `at' commands are setuid/setgid `atd'.
'';
};
};
};
};
in
###### implementation
let
cfg = config.services.atd; cfg = config.services.atd;
inherit (pkgs.lib) mkIf;
inherit (pkgs) at; inherit (pkgs) at;
user = { job =
name = "atd"; ''
uid = config.ids.uids.atd;
description = "atd user";
home = "/var/empty";
};
group = {
name = "atd";
gid = config.ids.gids.atd;
};
job = ''
description "at daemon (atd)" description "at daemon (atd)"
start on startup start on startup
@ -88,53 +50,67 @@ end script
respawn ${at}/sbin/atd respawn ${at}/sbin/atd
''; '';
in in
mkIf cfg.enable { {
require = [
options
# config.services.extraJobs ###### interface
#../upstart-jobs/default.nix
# config.environment.etc options = {
#../etc/default.nix
# users.* services.atd.enable = mkOption {
#../system/users-groups.nix default = true;
description = ''
Whether to enable the `at' daemon, a command scheduler.
'';
};
# ? # config.environment.extraPackages services.atd.allowEveryone = mkOption {
# ? # config.security.extraSetuidPrograms default = false;
]; description = ''
Whether to make /var/spool/at{jobs,spool} writeable
by everyone (and sticky). This is normally not needed since
the `at' commands are setuid/setgid `atd'.
'';
};
security = { };
setuidOwners = map (program: {
###### implementation
config = mkIf cfg.enable {
security.setuidOwners = map (program: {
inherit program; inherit program;
owner = "atd"; owner = "atd";
group = "atd"; group = "atd";
setuid = true; setuid = true;
setgid = true; setgid = true;
}) [ "at" "atq" "atrm" ]; }) [ "at" "atq" "atrm" ];
environment.systemPackages = [ at ];
security.pam.services = [ { name = "atd"; } ];
users.extraUsers = singleton
{ name = "atd";
uid = config.ids.uids.atd;
description = "atd user";
home = "/var/empty";
}; };
environment = { users.extraGroups = singleton
extraPackages = [ at ]; { name = "atd";
gid = config.ids.gids.atd;
etc = [{
source = ./atd.pam;
target = "pam.d/atd";
}];
}; };
users = { services.extraJobs = singleton # !!! convert to job
extraUsers = [user]; { name = "atd";
extraGroups = [group];
};
services = {
extraJobs = [{
name = "atd";
inherit job; inherit job;
}];
}; };
};
} }

View File

@ -1,4 +0,0 @@
auth include common
account include common
password include common
session include common

View File

@ -1,35 +1,15 @@
{pkgs, config, ...}: {pkgs, config, ...}:
###### interface with pkgs.lib;
let let
inherit (pkgs.lib) mkOption;
options = { dmcfg = config.services.xserver.displayManager;
services.xserver.displayManager.kdm = {
enable = mkOption {
default = false;
description = "
Whether to enable the KDE display manager.
";
};
};
};
in
###### implementation
let
xcfg = config.services.xserver;
dmcfg = xcfg.displayManager;
cfg = dmcfg.kdm; cfg = dmcfg.kdm;
inherit (pkgs.lib) mkIf;
inherit (pkgs) stdenv;
inherit (pkgs.kde42) kdebase_workspace; inherit (pkgs.kde42) kdebase_workspace;
kdmrc = stdenv.mkDerivation { kdmrc = pkgs.stdenv.mkDerivation {
name = "kdmrc"; name = "kdmrc";
# -e "s|Session=${kdebase_workspace}/share/config/kdm/Xsession|Session=${dmcfg.session.script}|" \ # -e "s|Session=${kdebase_workspace}/share/config/kdm/Xsession|Session=${dmcfg.session.script}|" \
buildCommand = '' buildCommand = ''
@ -50,20 +30,36 @@ let
in in
mkIf cfg.enable { {
require = [
options
];
services = { ###### interface
xserver = {
displayManager = { options = {
job = {
beforeScript = ""; services.xserver.displayManager.kdm = {
enable = mkOption {
default = false;
description = ''
Whether to enable the KDE display manager.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
services.xserver.displayManager.job =
{ beforeScript = "";
env = ""; env = "";
execCmd = "${kdebase_workspace}/bin/kdm -config ${kdmrc}/kdmrc"; execCmd = "${kdebase_workspace}/bin/kdm -config ${kdmrc}/kdmrc";
}; };
security.pam.services = [ { name = "slim"; localLogin = true; } ];
}; };
};
};
} }

View File

@ -1,83 +1,14 @@
{pkgs, config, ...}: {pkgs, config, ...}:
###### interface with pkgs.lib;
let let
inherit (pkgs.lib) mkOption;
slimOptions = { dmcfg = config.services.xserver.displayManager;
theme = mkOption {
default = null;
example = pkgs.fetchurl {
url = http://download.berlios.de/slim/slim-wave.tar.gz;
sha256 = "0ndr419i5myzcylvxb89m9grl2xyq6fbnyc3lkd711mzlmnnfxdy";
};
description = "
The theme for the SLiM login manager. If not specified, SLiM's
default theme is used. See <link
xlink:href='http://slim.berlios.de/themes01.php'/> for a
collection of themes.
";
};
defaultUser = mkOption {
default = "";
example = "login";
description = "
The default user to load. If you put a username here you
get it automatically loaded into the username field, and
the focus is placed on the password.
";
};
hideCursor = mkOption {
default = false;
example = true;
description = "
Hide the mouse cursor on the login screen.
";
};
};
options = { services = { xserver = { displayManager = {
slim = slimOptions // {
enable = mkOption {
default = true;
description = "
Whether to enable slim as the display manager.
";
};
};
}; /* displayManager */ }; /* xserver */ }; /* services */ };
copyOldOptions = { services = { xserver = {
# Declare old options.
slim = slimOptions;
# Copy the old options into the new options.
displayManager = {
slim = config.services.xserver.slim;
};
}; /* xserver */ }; /* services */ };
in
###### implementation
let
xcfg = config.services.xserver;
dmcfg = xcfg.displayManager;
cfg = dmcfg.slim; cfg = dmcfg.slim;
inherit (pkgs.lib) mkIf; slimConfig = pkgs.writeText "slim.cfg"
''
slimConfig = pkgs.writeText "slim.cfg" ''
xauth_path ${dmcfg.xauthBin} xauth_path ${dmcfg.xauthBin}
default_xserver ${dmcfg.xserverBin} default_xserver ${dmcfg.xserverBin}
xserver_arguments ${dmcfg.xserverArgs} xserver_arguments ${dmcfg.xserverArgs}
@ -89,7 +20,6 @@ let
${if cfg.hideCursor then "hidecursor true" else ""} ${if cfg.hideCursor then "hidecursor true" else ""}
''; '';
# Unpack the SLiM theme, or use the default. # Unpack the SLiM theme, or use the default.
slimThemesDir = slimThemesDir =
let let
@ -106,34 +36,77 @@ let
in in
mkIf cfg.enable { {
require = [
options
copyOldOptions
];
services = { ###### interface
xserver = {
displayManager = { options = {
job = {
beforeScript = '' services.xserver.displayManager.slim = {
enable = mkOption {
default = true;
description = ''
Whether to enable SLiM as the display manager.
'';
};
theme = mkOption {
default = null;
example = pkgs.fetchurl {
url = http://download.berlios.de/slim/slim-wave.tar.gz;
sha256 = "0ndr419i5myzcylvxb89m9grl2xyq6fbnyc3lkd711mzlmnnfxdy";
};
description = ''
The theme for the SLiM login manager. If not specified, SLiM's
default theme is used. See <link
xlink:href='http://slim.berlios.de/themes01.php'/> for a
collection of themes.
'';
};
defaultUser = mkOption {
default = "";
example = "login";
description = ''
The default user to load. If you put a username here you
get it automatically loaded into the username field, and
the focus is placed on the password.
'';
};
hideCursor = mkOption {
default = false;
example = true;
description = ''
Hide the mouse cursor on the login screen.
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
services.xserver.displayManager.job =
{ beforeScript =
''
rm -f /var/log/slim.log rm -f /var/log/slim.log
''; '';
env = '' env =
''
env SLIM_CFGFILE=${slimConfig} env SLIM_CFGFILE=${slimConfig}
env SLIM_THEMESDIR=${slimThemesDir} env SLIM_THEMESDIR=${slimThemesDir}
''; '';
execCmd = "${pkgs.slim}/bin/slim"; execCmd = "${pkgs.slim}/bin/slim";
}; };
};
}; security.pam.services = [ { name = "slim"; localLogin = true; } ];
}; };
environment = {
etc = [
{ source = ./slim.pam;
target = "pam.d/slim";
}
];
};
} }

View File

@ -1,5 +0,0 @@
auth include common
account include common
password include common
session include common
session include common-console