aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS11
-rw-r--r--doc/pam-modules.texi44
-rw-r--r--doc/pam_ldaphome.8in10
-rwxr-xr-xexamples/ldappubkey176
-rwxr-xr-xexamples/usergitconfig10
-rw-r--r--lib/env.c9
-rw-r--r--lib/graypam.h1
-rw-r--r--pam_ldaphome/pam_ldaphome.c38
8 files changed, 289 insertions, 10 deletions
diff --git a/NEWS b/NEWS
index 200204a..8406bd1 100644
--- a/NEWS
+++ b/NEWS
@@ -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",
diff --git a/lib/env.c b/lib/env.c
index 4ccb918..de63bbb 100644
--- a/lib/env.c
+++ b/lib/env.c
@@ -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
};

Return to:

Send suggestions and report system problems to the System administrator.