* 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, ...}:
with pkgs.lib;
let
inherit (pkgs) pam_unix2 pam_console pam_ldap;
# !!! ugh, these files shouldn't be created here.
pamConsoleHandlers = pkgs.writeText "console.handlers" ''
console consoledevs /dev/tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9]
@ -14,45 +18,122 @@ let
pamConsolePerms = ./console.perms;
generatePAMConfig = program:
let isLDAPEnabled = config.users.ldap.enable; in
{ source = pkgs.substituteAll {
src = ./pam.d + ("/" + program);
inherit (pkgs) pam_unix2 pam_console;
pam_ldap =
if isLDAPEnabled
then pkgs.pam_ldap
else "/no-such-path";
inherit (pkgs.xorg) xauth;
inherit pamConsoleHandlers;
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"
else "# change samba configuration options to make passwd sync the samba auth database as well here..";
};
target = "pam.d/" + program;
makePAMService =
{ name
, # If set, root doesn't need to authenticate (e.g. for the "chsh"
# service).
rootOK ? false
, # If set, this is a local login (e.g. virtual console or X), so
# the user gets ownership of audio devices etc.
localLogin ? false
, # Whether to forward XAuth keys between users. Mostly useful
# for "su".
forwardXAuth ? false
}:
{ source = pkgs.writeText "${name}.pam"
# !!! TODO: move the LDAP stuff to the LDAP module, and the
# Samba stuff to the Samba module. This requires that the PAM
# 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
{
environment.etc = map generatePAMConfig
[ "login"
"su"
"other"
"passwd"
"shadow"
"sshd"
"lshd"
"useradd"
"chsh"
"xlock"
"samba"
"cups"
"ftp"
"ejabberd"
"kde"
"common"
"common-console" # shared stuff for interactive local sessions
###### interface
options = {
security.pam.services = mkOption {
default = [];
example = [ { name = "chsh"; rootOK = true; } ];
description =
''
This option defines the PAM services. A service typically
corresponds to a program that uses PAM,
e.g. <command>login</command> or <command>passwd</command>.
Each element of this list is an attribute set describing a
service. The attribute <varname>name</varname> specifies
the name of the service. The attribute
<varname>rootOK</varname> specifies whether the root user is
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, ...}:
###### interface
with pkgs.lib;
let
inherit (pkgs.lib) mkOption;
cfg = config.security.sudo;
inherit (pkgs) sudo;
in
{
###### interface
options = {
security = {
sudo = {
enable = mkOption {
security.sudo.enable = mkOption {
default = true;
description = "
description =
''
Whether to enable the <command>sudo</command> command, which
allows non-root users to execute commands as root.
";
'';
};
configFile = mkOption {
default = "
# WARNING: do not edit this file directly or with \"visudo\". Instead,
security.sudo.configFile = mkOption {
# Note: if syntax errors are detected in this file, the NixOS
# 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.
# \"root\" is allowed to do anything.
# "root" is allowed to do anything.
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
";
description = "
'';
description =
''
This string contains the contents of the
<filename>sudoers</filename> file.
";
# If syntax errors are detected in this file, the NixOS
# configuration will fail to build.
'';
};
};
};
};
};
in
###### implementation
let
cfg = config.security.sudo;
inherit (pkgs.lib) mkIf;
inherit (pkgs) sudo;
in
mkIf cfg.enable {
require = [
options
config = mkIf cfg.enable {
# config.environment.etc
# ../etc/default.nix
security.extraSetuidPrograms = [ "sudo" ];
# ? # config.environment.extraPackages
# ? # config.security.extraSetuidPrograms
];
environment.systemPackages = [ sudo ];
security = {
extraSetuidPrograms = [
"sudo"
];
};
security.pam.services = [ { name = "sudo"; } ];
environment = {
extraPackages = [ sudo ];
etc = [
{
source = ./sudo.pam;
target = "pam.d/sudo";
}
{
source = pkgs.runCommand "sudoers"
environment.etc = singleton
{ source = pkgs.runCommand "sudoers"
{ src = pkgs.writeText "sudoers-in" cfg.configFile; }
# Make sure that the sudoers file is syntactically valid.
# (currently disabled - NIXOS-66)
@ -81,7 +67,8 @@ mkIf cfg.enable {
"cp $src $out";
target = "sudoers";
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, ...}:
###### interface
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
with pkgs.lib;
let
startingDependency = if config.services.gw6c.enable then "gw6c" else "network-interfaces";
@ -61,7 +23,6 @@ let
disable_plaintext_auth = no
'')
+ ''
login_user = ${cfg.user}
login_chroot = no
@ -84,48 +45,78 @@ let
pop3_uidl_format = %08Xv%08Xu
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
mkIf config.services.dovecot.enable {
{
require = [
options
];
###### interface
environment = {
etc = [{
source = pamdFile;
target = "pam.d/dovecot";
}];
options = {
services.dovecot = {
enable = mkOption {
default = false;
description = "Whether to enable the Dovecot POP3/IMAP server.";
};
users = {
extraUsers = [{
name = cfg.user;
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 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;
description = "Dovecot user";
group = cfg.group;
}];
extraGroups = [{
name = cfg.group;
gid = config.ids.gids.dovecot;
}];
};
services = {
extraJobs = [{
name = "dovecot";
users.extraGroups = singleton
{ name = cfg.group;
gid = config.ids.gids.dovecot;
};
job = ''
services.extraJobs = singleton
{ name = "dovecot";
job =
''
description "Dovecot IMAP/POP3 server"
start on ${startingDependency}/started
@ -138,7 +129,8 @@ mkIf config.services.dovecot.enable {
respawn ${pkgs.dovecot}/sbin/dovecot -F -c ${confFile}
'';
}];
};
};
}

View File

@ -1,53 +1,15 @@
{pkgs, config, ...}:
###### interface
with pkgs.lib;
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;
inherit (pkgs.lib) mkIf;
inherit (pkgs) at;
user = {
name = "atd";
uid = config.ids.uids.atd;
description = "atd user";
home = "/var/empty";
};
group = {
name = "atd";
gid = config.ids.gids.atd;
};
job = ''
job =
''
description "at daemon (atd)"
start on startup
@ -88,53 +50,67 @@ end script
respawn ${at}/sbin/atd
'';
in
mkIf cfg.enable {
require = [
options
{
# config.services.extraJobs
#../upstart-jobs/default.nix
###### interface
# config.environment.etc
#../etc/default.nix
options = {
# users.*
#../system/users-groups.nix
services.atd.enable = mkOption {
default = true;
description = ''
Whether to enable the `at' daemon, a command scheduler.
'';
};
# ? # config.environment.extraPackages
# ? # config.security.extraSetuidPrograms
];
services.atd.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'.
'';
};
security = {
setuidOwners = map (program: {
};
###### implementation
config = mkIf cfg.enable {
security.setuidOwners = map (program: {
inherit program;
owner = "atd";
group = "atd";
setuid = true;
setgid = true;
}) [ "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 = {
extraPackages = [ at ];
etc = [{
source = ./atd.pam;
target = "pam.d/atd";
}];
users.extraGroups = singleton
{ name = "atd";
gid = config.ids.gids.atd;
};
users = {
extraUsers = [user];
extraGroups = [group];
};
services = {
extraJobs = [{
name = "atd";
services.extraJobs = singleton # !!! convert to job
{ name = "atd";
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, ...}:
###### interface
with pkgs.lib;
let
inherit (pkgs.lib) mkOption;
options = {
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;
dmcfg = config.services.xserver.displayManager;
cfg = dmcfg.kdm;
inherit (pkgs.lib) mkIf;
inherit (pkgs) stdenv;
inherit (pkgs.kde42) kdebase_workspace;
kdmrc = stdenv.mkDerivation {
kdmrc = pkgs.stdenv.mkDerivation {
name = "kdmrc";
# -e "s|Session=${kdebase_workspace}/share/config/kdm/Xsession|Session=${dmcfg.session.script}|" \
buildCommand = ''
@ -50,20 +30,36 @@ let
in
mkIf cfg.enable {
require = [
options
];
{
services = {
xserver = {
displayManager = {
job = {
beforeScript = "";
###### interface
options = {
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 = "";
execCmd = "${kdebase_workspace}/bin/kdm -config ${kdmrc}/kdmrc";
};
security.pam.services = [ { name = "slim"; localLogin = true; } ];
};
};
};
}

View File

@ -1,83 +1,14 @@
{pkgs, config, ...}:
###### interface
with pkgs.lib;
let
inherit (pkgs.lib) mkOption;
slimOptions = {
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;
dmcfg = config.services.xserver.displayManager;
cfg = dmcfg.slim;
inherit (pkgs.lib) mkIf;
slimConfig = pkgs.writeText "slim.cfg" ''
slimConfig = pkgs.writeText "slim.cfg"
''
xauth_path ${dmcfg.xauthBin}
default_xserver ${dmcfg.xserverBin}
xserver_arguments ${dmcfg.xserverArgs}
@ -89,7 +20,6 @@ let
${if cfg.hideCursor then "hidecursor true" else ""}
'';
# Unpack the SLiM theme, or use the default.
slimThemesDir =
let
@ -106,34 +36,77 @@ let
in
mkIf cfg.enable {
require = [
options
copyOldOptions
];
{
services = {
xserver = {
displayManager = {
job = {
beforeScript = ''
###### interface
options = {
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
'';
env = ''
env =
''
env SLIM_CFGFILE=${slimConfig}
env SLIM_THEMESDIR=${slimThemesDir}
'';
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