diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-05-19 13:49:03 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-05-19 14:01:21 +0300 |
commit | 7636fa3e7b5829adebf003f3150ae14372cdaae5 (patch) | |
tree | f394870ed1a4c5ea7a2f5cf4debaa91b57f8b856 | |
parent | 867eaccec7a1324f958d0d86c1a148187212bf6f (diff) | |
download | pam-modules-7636fa3e7b5829adebf003f3150ae14372cdaae5.tar.gz pam-modules-7636fa3e7b5829adebf003f3150ae14372cdaae5.tar.bz2 |
New utility "ldappubkey".
* NEWS: Document new features.
* doc/pam-modules.texi: Document usergitconfig.
* doc/pam_ldaphome.8in: Update.
* examples/ldappubkey: New file.
* examples/usergitconfig: Refer to perldoc on error.
* lib/env.c (gray_env_get_bool): New function.
* lib/graypam.h (gray_env_get_bool): New proto.
* pam_ldaphome/pam_ldaphome.c (import_public_key): Do nothing if
"import-public-keys" is set to "no".
(pam_sm_authenticate): New function.
-rw-r--r-- | NEWS | 11 | ||||
-rw-r--r-- | doc/pam-modules.texi | 44 | ||||
-rw-r--r-- | doc/pam_ldaphome.8in | 10 | ||||
-rwxr-xr-x | examples/ldappubkey | 176 | ||||
-rwxr-xr-x | examples/usergitconfig | 10 | ||||
-rw-r--r-- | lib/env.c | 9 | ||||
-rw-r--r-- | lib/graypam.h | 1 | ||||
-rw-r--r-- | pam_ldaphome/pam_ldaphome.c | 38 |
8 files changed, 289 insertions, 10 deletions
@@ -1,4 +1,4 @@ -pam-modules -- history of user-visible changes. 2014-05-06 +pam-modules -- history of user-visible changes. 2014-05-11 Copyright (C) 2001, 2004-2005, 2007-2012, 2014 Sergey Poznyakoff See the end of file for copying conditions. @@ -11,6 +11,15 @@ Version 1.8.92, (Git) Tests whether the user is a member of one or more groups. +* pam_ldaphome can invoke an external program + +An external program defined with the inirc-command keyword is run +in the newly created user's home directory. It can be used for +per-user customization of the files copied from the skeleton dir. + +The examples directory contains a perl program "usergitconfig", which, +when used as inirc-command, initializes the user's .gitconfig file. + * Bugfixes diff --git a/doc/pam-modules.texi b/doc/pam-modules.texi index 87c4d6c..bf101f7 100644 --- a/doc/pam-modules.texi +++ b/doc/pam-modules.texi @@ -1249,6 +1249,12 @@ Sets the LDAP filter expression to return a user profile. The filters as defined in RFC 4515. @end deffn +@deffn {pam_ldaphome config} import-public-keys bool +When set to @samp{no}, disables importing public keys from LDAP. You +may wish to use this option if you are using @command{openssh} 6.1 or +later with @command{ldappubkey} as @samp{AuthorizedKeysCommand}. +@end deffn + @deffn {pam_ldaphome config} pubkey-attr text Defines the name of the attribute which holds the user public key. @end deffn @@ -1351,6 +1357,7 @@ which case the usual shell dequoting rules apply. @menu * ldaphome example:: +* usergitconfig:: @end menu @node ldaphome example @@ -1437,6 +1444,43 @@ passwd: files ldap group: files ldap @end example +@node usergitconfig +@section usergitconfig +@cindex usergitconfig + +The @file{examples} subdirectory of the @command{pam-modules} +distribution contains a program @command{usergitconfig} which +is designed to customize user's @file{.gitconfig} file using +attributes from his LDAP entry. + +The command reads the @file{.gitconfig} file and replaces any +occurrence of @samp{$@{@var{attr}@}} with the value of the LDAP +attribute @var{attr}. Not defined attributes are replaced with +empty strings. + +To use this utility with @command{pam_ldaphome}, copy it to +some location of preference (say, @file{/usr/libexec}), and +add the following to @command{pam_ldaphome} configuration file: + +@example +skel /etc/skel +initrc-command /usr/libexec/usergitconfig +@end example + +The @file{/etc/skel} directory should contain the file @file{.gitconfig}. +Suppose its contents is as follows: + +@example +[user] + name = $@{cn@} + email = $@{mail@} +@end example + +@noindent +Then, after successful completion of @command{pam_ldaphome}, the +user's @file{.gitconfig} file will contain his real name and email +set properly from the database. + @node umotd @chapter pam_umotd @set MODULE pam_umotd diff --git a/doc/pam_ldaphome.8in b/doc/pam_ldaphome.8in index 6d74e4e..5150849 100644 --- a/doc/pam_ldaphome.8in +++ b/doc/pam_ldaphome.8in @@ -14,7 +14,7 @@ .\" You should have received a copy of the GNU General Public License .\" along with PAM-Modules. If not, see <http://www.gnu.org/licenses/>. .so config.so -.TH PAM_LDAPHOME 8 "April 4, 2014" "PAM-MODULES" "Pam-Modules User Reference" +.TH PAM_LDAPHOME 8 "May 19, 2014" "PAM-MODULES" "Pam-Modules User Reference" .SH NAME pam_ldaphome \- create and populate user home directories .SH SYNOPSIS @@ -108,6 +108,11 @@ Defines a LDAP filter expression which returns the user profile. The \fIEXPR\fR should conform to the string representation for search filters as defined in RFC 4515. .TP +.BI import\-public\-keys " BOOL" +When set to \fBno\fR, disables importing public keys from LDAP. You +may wish to use this option if you are using \fBopenssh\fR 6.1 or +later with \fBldappubkey\fR as \fBAuthorizedKeysCommand\fR. +.TP .BI pubkey\-attr " TEXT" Defines the name of the attribute that keeps user's public SSH key. .TP @@ -203,7 +208,8 @@ the \fB\-\-enable\-debug\fR option. \fBaudit\fR Log auditing information. .SH MODULE TYPES PROVIDED -.BR auth . +.BR auth , +.BR session . .SH RETURN VALUES .TP .B PAM_SUCCESS diff --git a/examples/ldappubkey b/examples/ldappubkey new file mode 100755 index 0000000..2451505 --- /dev/null +++ b/examples/ldappubkey @@ -0,0 +1,176 @@ +#! /usr/bin/perl +# This file is part of pam-modules. +# Copyright (C) 2014 Sergey Poznyakoff +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. + +use strict; +use Net::LDAP; + +=head1 NAME + +ldappubkey - get user public ssh keys from the LDAP database + +=head1 SYNOPSIS + +B<ldappubkey> I<LOGIN> + +=head1 DESCRIPTION + +Produces on the standard output public ssh keys for the user I<LOGIN>, each +on a separate line. The program is designed for use with B<sshd>(8) version +6.x or higher. Public keys are obtained from a LDAP database. The +configuration is looked up in the following files: B</etc/ldap.conf>, +B</etc/ldap/ldap.conf> and B</etc/openldap/ldap.conf>. These files are +tried in this order and the first one of them that exists is read. + +The following configuration statements are used (all keywords are +case-insensitive): + +=over 4 + +=item B<uri> B<ldap[si]://>[I<name>[:I<port>]] ...> + +Specifies the URI of the LDAP server (or servers) to connect to. The default +is B<ldap://127.0.0.1>. + +=item B<base> I<DN> + +Specifies the default base DN to use when performing ldap operations. +The base must be specified as a Distinguished Name in LDAP format. + +=item B<binddn> I<DN> + +Specifies the default bind DN to use. + +=item B<bindpw> I<PASS> + +Specifies the password to use with B<binddn>. + +=item B<uid> I<ATTR> + +Name of the attribute to use instead of B<uid>. The LDAP record is searched +using the filter B<(&(objectClass=posixAccount)(I<ATTR>=I<LOGIN>))>. + +=item B<publickeyattribute> I<ATTR> + +Name of the attribute which holds the public key. Default is B<grayPublicKey>. + +=back + +=head1 OPTIONS + +=over 4 + +=item B<-h> + +Show program usage. + +=item B<--help> + +Show detailed help page. + +=back + +=head1 SEE ALSO + +B<sshd>(8), B<sshd_config>(5), B<ldap.conf>(5). + +=head1 BUGS + +LDAP filter string is hardcoded. + +=head1 AUTHOR + +Sergey Poznyakoff <gray@gnu.org> + +=cut + +# ################################### +# Configuration file handling +# ################################### + +my %config = ('uri' => 'ldap://127.0.0.1', 'uid' => 'uid', + 'publickeyattribute' => 'grayPublicKey'); + +sub read_config_file($) { + my $config_file = shift; + my $file; + my $line = 0; + + open($file, "<", $config_file) or die("cannot open $config_file: $!"); + while (<$file>) { + ++$line; + chomp; + s/^\s+//; + s/\s+$//; + s/#.*//; + next if ($_ eq ""); + my @kwp = split(/\s*\s+\s*/, $_, 2); + $config{lc($kwp[0])} = $kwp[1]; + } + close($file); +} + +sub assert { + my $mesg = shift; + my $action = shift; + die("An error occurred $action: ".$mesg->error) if ($mesg->code); + return $mesg; +} + +# ################################### +# MAIN +# ################################### + +die "bad number of arguments; try perldoc $0 for more info" + unless ($#ARGV == 0); + +## Read configuration +foreach my $file ("/etc/ldap.conf", "/etc/ldap/ldap.conf", + "/etc/openldap/ldap.conf") { + if (-e $file) { + read_config_file($file); + last; + } +} + +my $ldap = Net::LDAP->new($config{'uri'}) + or die("Unable to connect to LDAP server $config{'uri'}: $!"); +my @bindargs = (); +if (defined($config{'binddn'})) { + push(@bindargs, $config{'binddn'}); + push(@bindargs, password => $config{'bindpw'}) + if defined($config{'bindpw'}); +} +assert($ldap->bind(@bindargs), "binding to the server"); + +my $attr = $config{'publickeyattribute'}; +my $filter = "(&(objectClass=posixAccount)($config{'uid'}=$ARGV[0]))"; + +my $res = assert($ldap->search(base => $config{'base'}, + filter => $filter, + attr => [ $attr ] ), + "searching for $filter in $config{'base'}"); + +foreach my $entry ($res->entry(0)) { + my $keyref = $entry->get_value($attr, asref => 1); + for (@{$keyref}) { + print "$_\n"; + } +} + +# END + + diff --git a/examples/usergitconfig b/examples/usergitconfig index 16ae36b..924bd6f 100755 --- a/examples/usergitconfig +++ b/examples/usergitconfig @@ -78,6 +78,13 @@ is written to B<.gitconfig>. The program is intended to be used in B<initrc-command> keyword of the B<pam_ldaphome>(8) configuration file. +Example B<.gitconfig> file: + + [user] + name = ${cn} + email = ${mail} + + =head1 SEE ALSO B<pam_ldaphome>(8), B<ldap.conf>(5). @@ -141,7 +148,8 @@ sub ldap_connect { # MAIN # ################################### -die "bad number of arguments" unless ($#ARGV == 0); +die "bad number of arguments; try perldoc $0 for more info" + unless ($#ARGV == 0); ## Read configuration foreach my $file ("/etc/ldap.conf", "/etc/ldap/ldap.conf", @@ -25,6 +25,15 @@ gray_env_get(struct gray_env *env, const char *name) return NULL; } +int +gray_env_get_bool(struct gray_env *env, const char *name, int dfl) +{ + char *p = gray_env_get(env, name); + if (!p) + return dfl; + return gray_boolean_true_p(p); +} + void gray_env_free(struct gray_env *env) { diff --git a/lib/graypam.h b/lib/graypam.h index 8d0e1c0..636e4fb 100644 --- a/lib/graypam.h +++ b/lib/graypam.h @@ -209,6 +209,7 @@ struct gray_env { }; char *gray_env_get(struct gray_env *env, const char *name); +int gray_env_get_bool(struct gray_env *env, const char *name, int dfl); void gray_env_free(struct gray_env *env); int gray_env_read(const char *file_name, struct gray_env **penv); diff --git a/pam_ldaphome/pam_ldaphome.c b/pam_ldaphome/pam_ldaphome.c index 1df9de0..f89b151 100644 --- a/pam_ldaphome/pam_ldaphome.c +++ b/pam_ldaphome/pam_ldaphome.c @@ -1321,6 +1321,9 @@ import_public_key(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env) const char *filter_pat = gray_env_get(env, "filter"); const char *attr = gray_env_get(env, "pubkey-attr"); + if (!gray_env_get_bool(env, "import-public-keys", 1)) + return PAM_SUCCESS; + if (!filter_pat) { _pam_log(LOG_ERR, "configuration variable `filter' not set"); return PAM_SERVICE_ERR; @@ -1855,15 +1858,16 @@ run_initrc(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env) return rc; } -PAM_EXTERN int -pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) +static int +ldaphome_main(pam_handle_t *pamh, int flags, int argc, const char **argv, + const char *func) { int retval = PAM_AUTH_ERR; struct gray_env *env; _pam_parse(pamh, argc, argv); - DEBUG(90,("enter pam_sm_authenticate")); + DEBUG(90,("enter %s", func)); gray_pam_init(PAM_AUTHINFO_UNAVAIL); if (gray_env_read(config_file_name, &env) == 0) { char *val; @@ -1889,10 +1893,18 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) } gray_env_free(env); } - DEBUG(90,("exit pam_sm_authenticate: %d", retval)); + DEBUG(90,("exit %s: %d", func, retval)); return retval; } + + +PAM_EXTERN int +pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) +{ + return ldaphome_main(pamh, flags, argc, argv, __FUNCTION__); +} + PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, @@ -1902,6 +1914,20 @@ pam_sm_setcred(pam_handle_t *pamh, return PAM_SUCCESS; } +PAM_EXTERN int +pam_sm_open_session (pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + return ldaphome_main(pamh, flags, argc, argv, __FUNCTION__); +} + +PAM_EXTERN int +pam_sm_close_session (pam_handle_t *pamh, int flags, int argc, + const char **argv) +{ + return PAM_SUCCESS; +} + #ifdef PAM_STATIC struct pam_module _pam_ldaphome_modstruct = { @@ -1909,8 +1935,8 @@ struct pam_module _pam_ldaphome_modstruct = { pam_sm_authenticate, pam_sm_setcred, NULL, - NULL, - NULL, + pam_sm_open_session, + pam_sm_close_session, NULL }; |