summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2014-07-25 12:09:33 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2014-07-25 12:37:28 (GMT)
commitb4a27a9c7afc21d7a4895cddc5c182c3349f1f11 (patch) (side-by-side diff)
tree9808605942a1c52af52fcb9c3cdbe14925bd370b
parentc1059e03983d704ea79cf97d9cffb2cbaa79bcae (diff)
downloadpam-modules-b4a27a9c7afc21d7a4895cddc5c182c3349f1f11.tar.gz
pam-modules-b4a27a9c7afc21d7a4895cddc5c182c3349f1f11.tar.bz2
pam_ldaphome: read /etc/ldap.conf file.
* lib/env.c (gray_env_read_tr): New function. (gray_env_read): Rewrite using gray_env_read_tr. (gray_env_merge): New function. * lib/escape.c (gray_escape_string): Remove useless typecasts. * lib/graypam.h (gray_env_read_tr) (gray_env_merge): New protos. * pam_ldaphome/pam_ldaphome.c (ldap_config_name): New variable. (ldap_connect): Use 'ssl' keyword, if 'tls' is not defined. (ldaphome_main): New keyword ldap-config * doc/pam-modules.texi: Document reading system-wide ldap.conf * doc/pam_ldaphome.8in: Likewise.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--doc/pam-modules.texi179
-rw-r--r--doc/pam_ldaphome.8in28
-rw-r--r--lib/env.c58
-rw-r--r--lib/escape.c8
-rw-r--r--lib/graypam.h2
-rw-r--r--pam_ldaphome/pam_ldaphome.c75
6 files changed, 249 insertions, 101 deletions
diff --git a/doc/pam-modules.texi b/doc/pam-modules.texi
index 12c58cd..57242cf 100644
--- a/doc/pam-modules.texi
+++ b/doc/pam-modules.texi
@@ -1179,36 +1179,45 @@ Read configuration from @var{file}. Default is
@file{pam_ldaphome.conf} in @var{sysconfdir}.
@end table
-Actual module configuration is read from the configuration file, which
-has the same syntax as described in @ref{config, SQL configuration
-file}. The following keywords are defined:
+Actual module configuration is read from the configuration file.
-@deffn {pam_ldaphome config} allow-home-dir @var{path}
-If present, this option controls where @command{pam_ldaphome} should
-try to create home directories. Its value is a list of directories
-separated by colons. The user's home directory will be created only
-if the directory part of its name is listed in @var{path}.
-@end deffn
+@menu
+* ldaphome config::
+* ldaphome example::
+* ldappubkey::
+* usergitconfig::
+@end menu
-@deffn {pam_ldaphome config} skel @var{dir}
-Supplies the name of a @dfn{skeleton directory}. The contents of this
-directory is copied to the newly created user home directory. The
-file modes and permissions are preserved.
-@end deffn
+@node ldaphome config
+@section Configuration file for @command{pam_ldaphome}
-@deffn {pam_ldaphome config} uri @var{arg}
-Sets the URI of the LDAP server to consult for the user profile.
-Example:
+@command{Pam_ldaphome} reads its configuration from two files: the
+configuration file supplied with the @command{config} command line
+option and the system-wide LDAP configuration file
+@file{/etc/ldap.conf}.
-@example
-uri ldap://127.0.0.1/
-@end example
-@end deffn
+The syntax of the former is described in @ref{config, SQL configuration
+file}. Allowed keywords are discussed below.
-@deffn {pam_ldaphome config} ldap-version @var{v}
-Sets the LDAP version to use. Valid values for @var{v} are @samp{2}
-and @samp{3} (the default).
-@end deffn
+The syntax of the @file{/etc/ldap.conf} configuration file is
+described in @ref{ldap.conf,,LDAP configuration file,ldap.conf(5),
+ldap.conf(5) manpage}. Its parsing can be suppressed using the
+@command{ldap-config} statement (see below).
+
+From @file{/etc/ldap.conf}, the following statements are used:
+@samp{base}, @samp{binddn}, @samp{bindpw}, @samp{tls_cacert},
+@samp{uri}. The @samp{ssl} statement is understood if its value is
+@samp{start_tls} or @samp{off}. Other values are silently ignored.
+
+In general, all statements defined below can appear in both files.
+However, since @file{/etc/ldap.conf} is read by other system utilities
+as well, we do not recomment using @command{pam_ldaphome}-specific
+keywords in it.
+
+The values read from @command{pam_ldaphome} configuration file
+override those obtained from the standard LDAP configuration file.
+
+@subheading LDAP configuration
@deffn {pam_ldaphome config} base @var{searchbase}
Use @var{searchbase} as the starting point for the search instead of
@@ -1237,6 +1246,27 @@ password for simple authentication.
Read password for simple authentication from @var{file}.
@end deffn
+@deffn {pam_ldaphome config} filter @var{expr}
+Sets the LDAP filter expression to return a user profile. The
+@var{expr} should conform to the string representation for search
+filters as defined in RFC 4515.
+@end deffn
+
+@deffn {pam_ldaphome config} ldap-config @var{file}
+Read LDAP configuration from @var{file} (default --
+@file{/etc/ldap.conf}). Special value @samp{none} disables this
+feature.
+@end deffn
+
+@deffn {pam_ldaphome config} ldap-version @var{v}
+Sets the LDAP version to use. Valid values for @var{v} are @samp{2}
+and @samp{3} (the default).
+@end deffn
+
+@deffn {pam_ldaphome config} pubkey-attr @var{text}
+Defines the name of the attribute which holds the user public key.
+@end deffn
+
@deffn {pam_ldaphome config} tls @var{val}
Controls whether TLS is desired or required. If @var{val} is
@samp{no} (the default), TLS will not be used. If it is @samp{yes},
@@ -1247,41 +1277,27 @@ mandatory, and the module will not establish LDAP connection unless
@end deffn
@deffn {pam_ldaphome config} tls-cacert @var{val}
+@deffnx {pam_ldaphome config} tls_cacert @var{val}
Full pathname to the CA certificate file. Used if TLS is enabled.
+The second form (@samp{tls_cacert}) is for use in
+@file{/etc/ldap.conf} file.
@end deffn
-@deffn {pam_ldaphome config} min-uid @var{n}
-Sets the minimal UID. For users with UIDs less than @var{n},
-@command{pam_ldaphome} returns PAM_SUCCESS immediately. This allows
-you to have a set of basic users whose credentials are kept in the
-system database and who will not be disturbed by
-@command{pam_ldaphome}. See also @samp{min-gid} and
-@samp{allow-groups}.
-@end deffn
-
-@deffn {pam_ldaphome config} min-gid @var{n}
-Sets the minimal GID. For users with GIDs less than @var{n},
-@command{pam_ldaphome} returns PAM_SUCCESS immediately.
-@end deffn
-
-@deffn {pam_ldaphome config} allow-groups @var{group} [@var{group}...]
-Only handle members of the listed groups.
-@end deffn
-
-@deffn {pam_ldaphome config} filter @var{expr}
-Sets the LDAP filter expression to return a user profile. The
-@var{expr} should conform to the string representation for search
-filters as defined in RFC 4515.
-@end deffn
+@deffn {pam_ldaphome config} uri @var{arg}
+Sets the URI of the LDAP server to consult for the user profile.
+Example:
-@deffn {pam_ldaphome config} import-public-keys @var{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}.
+@example
+uri ldap://127.0.0.1/
+@end example
@end deffn
-@deffn {pam_ldaphome config} pubkey-attr @var{text}
-Defines the name of the attribute which holds the user public key.
+@subheading Home directory creation
+@deffn {pam_ldaphome config} allow-home-dir @var{path}
+If present, this option controls where @command{pam_ldaphome} should
+try to create home directories. Its value is a list of directories
+separated by colons. The user's home directory will be created only
+if the directory part of its name is listed in @var{path}.
@end deffn
@deffn {pam_ldaphome config} copy-buf-size @var{n}
@@ -1293,10 +1309,13 @@ directory to the newly created home. The default size is 16384 bytes.
Sets the mode (octal) for the created user directories.
@end deffn
-@deffn {pam_ldaphome config} keyfile-mode @var{mode}
-Sets the mode (octal) for the created authorized keys file.
+@deffn {pam_ldaphome config} skel @var{dir}
+Supplies the name of a @dfn{skeleton directory}. The contents of this
+directory is copied to the newly created user home directory. The
+file modes and permissions are preserved.
@end deffn
+@subheading Authorized keys file
@deffn {pam_ldaphome config} authorized_keys @var{name}
Sets the pathname (relative to the home directory) for the authorized
keys file. The default is @samp{.ssh/authorized_keys}. For normal
@@ -1305,11 +1324,47 @@ operation, this value must be the same as the value of
change the latter, there's no need to edit it.
@end deffn
+@deffn {pam_ldaphome config} import-public-keys @var{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} keyfile-mode @var{mode}
+Sets the mode (octal) for the created authorized keys file.
+@end deffn
+
+@subheading Access control
+@deffn {pam_ldaphome config} allow-groups @var{group} [@var{group}...]
+Only handle members of the listed groups.
+@end deffn
+
+@deffn {pam_ldaphome config} min-gid @var{n}
+Sets the minimal GID. For users with GIDs less than @var{n},
+@command{pam_ldaphome} returns PAM_SUCCESS immediately.
+@end deffn
+
+@deffn {pam_ldaphome config} min-uid @var{n}
+Sets the minimal UID. For users with UIDs less than @var{n},
+@command{pam_ldaphome} returns PAM_SUCCESS immediately. This allows
+you to have a set of basic users whose credentials are kept in the
+system database and who will not be disturbed by
+@command{pam_ldaphome}. See also @samp{min-gid} and
+@samp{allow-groups}.
+@end deffn
+
+@subheading Initialization script
The following statements instruct @command{pam_ldaphome} to invoke an
external command after initializing the user home directory. This can
be used to customize the files copied from the skeleton directory
according to the user.
+@deffn {pam_ldaphome config} exec-timeout @var{seconds}
+Sets maximum time the @command{initrc-command} is allowed to run. If
+it runs longer than @var{seconds}, it will be terminated with a
+@samp{SIGKILL}, and the module will return PAM_SYSTEM_ERR.
+@end deffn
+
@deffn {pam_ldaphome config} initrc-command @var{command}
Run @command{command} after populating the user home directory with
files from the skeleton directory.
@@ -1324,12 +1379,6 @@ non-zero code, @command{pam_ldaphome} will report
@samp{PAM_SYSTEM_ERR}.
@end deffn
-@deffn {pam_ldaphome config} exec-timeout @var{seconds}
-Sets maximum time the @command{initrc-command} is allowed to run. If
-it runs longer than @var{seconds}, it will be terminated with a
-@samp{SIGKILL}, and the module will return PAM_SYSTEM_ERR.
-@end deffn
-
@deffn {pam_ldaphome config} initrc-log @var{file}
This statement redirects the standard output and error from the
@command{initrc-command} to @var{file}.
@@ -1386,12 +1435,6 @@ The @var{value} part can be enclosed in single or double quotes, in
which case the usual shell dequoting rules apply.
@end deffn
-@menu
-* ldaphome example::
-* ldappubkey::
-* usergitconfig::
-@end menu
-
@node ldaphome example
@section Example of pam_ldaphome configuration
This example assumes you are using GNU/Linux. The aim of this
diff --git a/doc/pam_ldaphome.8in b/doc/pam_ldaphome.8in
index 97f75d6..416e7c6 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 "July 24, 2014" "PAM-MODULES" "Pam-Modules User Reference"
+.TH PAM_LDAPHOME 8 "July 25, 2014" "PAM-MODULES" "Pam-Modules User Reference"
.SH NAME
pam_ldaphome \- create and populate user home directories
.SH SYNOPSIS
@@ -43,7 +43,21 @@ The configuration is kept in the file
The file is a usual UNIX-style configuration file with
comments introduced by the \fB#\fR character. Long statements can be
split across several physical lines of text by ending each line but
-the last with a backslash character.
+the last with a backslash character.
+.PP
+The system-wide configuration file
+.B /etc/ldap.conf
+is parsed after processing the main configuration file. In general,
+all statements defined below can appear in both files. However, since
+.B /etc/ldap.conf
+is read by other system utilities as well, we do not recomment using
+.BR pam_ldaphome -specific
+keywords in it.
+.PP
+The values from
+.B \*(ET/pam_ldaphome.conf
+override those obtained from
+.BR /etc/ldap.conf .
.PP
Available configuration directives are:
.SS LDAP Settings
@@ -66,6 +80,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 ldap\-config " FILE"
+Read LDAP configuration from \fIFILE\fR (default --
+\fB/etc/ldap.conf\fR). Special value \fBnone\fR disables reading
+this file.
+.TP
.BI ldap\-version " NUM"
Sets the LDAP version to use. Valid arguments are
.B 2
@@ -86,6 +105,11 @@ connection unless \fIStartTLS\fR succeeds.
.TP
.BI tls-cacert " VAL"
Full pathname to the CA certificate file. Used if TLS is enabled.
+The form
+.B tls_cacert
+is also understood (for use in
+.B /etc/ldap.conf
+file).
.TP
.BI uri " ARG"
Sets the URI of the LDAP server to consult for the user profile.
diff --git a/lib/env.c b/lib/env.c
index de63bbb..0a69881 100644
--- a/lib/env.c
+++ b/lib/env.c
@@ -45,8 +45,39 @@ gray_env_free(struct gray_env *env)
}
}
+static void
+tr(char *input, char **map)
+{
+ unsigned char *s = (unsigned char*) input;
+
+ for (; *s; s++) {
+ unsigned char *f = (unsigned char *)map[0];
+ unsigned char *t = (unsigned char *)map[1];
+ for (; *f && *t; f++, t++) {
+ if (f > (unsigned char *)map[0]
+ && *f == '-' && *t == '-'
+ && f[1] && t[1]) {
+ int a = f[-1];
+ int d = f[1] - a;
+
+ if ((d > 0
+ && a < *s && *s <= a + d)
+ || (d < 0
+ && (a + d <= *s && *s < a))) {
+ *s = t[-1] + *s - a;
+ break;
+ }
+ ++f; ++t;
+ } else if (*f == *s) {
+ *s = *t;
+ break;
+ }
+ }
+ }
+}
+
int
-gray_env_read(const char *file_name, struct gray_env **penv)
+gray_env_read_tr(const char *file_name, struct gray_env **penv, char **trmap)
{
FILE *fp;
char *p;
@@ -63,7 +94,6 @@ gray_env_read(const char *file_name, struct gray_env **penv)
return 1;
}
- config_env = NULL;
while (p = fgets(buf, sizeof buf, fp)) {
int len;
struct gray_env *env;
@@ -147,6 +177,8 @@ gray_env_read(const char *file_name, struct gray_env **penv)
;
if (*p)
*p++ = 0;
+ if (trmap)
+ tr(env->name, trmap);
for (; *p && isspace(*p); p++)
;
if (!*p) {
@@ -168,6 +200,28 @@ gray_env_read(const char *file_name, struct gray_env **penv)
}
int
+gray_env_read(const char *file_name, struct gray_env **penv)
+{
+ return gray_env_read_tr(file_name, penv, NULL);
+}
+
+void
+gray_env_merge(struct gray_env **pa, struct gray_env **pb)
+{
+ if (!*pa)
+ *pa = *pb;
+ else if (!*pb)
+ return;
+ else {
+ struct gray_env *a;
+ for (a = *pa; a->next; a = a->next)
+ ;
+ a->next = *pb;
+ }
+ *pb = NULL;
+}
+
+int
gray_boolean_true_p(const char *value)
{
return strcmp(value, "yes") == 0
diff --git a/lib/escape.c b/lib/escape.c
index 7a5f07d..bf044f3 100644
--- a/lib/escape.c
+++ b/lib/escape.c
@@ -17,15 +17,15 @@
#include <graypam.h>
void
-gray_escape_string (gray_slist_t slist, const char *str, size_t len)
+gray_escape_string(gray_slist_t slist, const char *str, size_t len)
{
- const unsigned char *p;
+ const char *p;
#define ESCAPABLE_CHAR "\\'\""
#define FLUSH() \
- gray_slist_append(slist, str, p - (const unsigned char *)str); \
+ gray_slist_append(slist, str, p - str); \
str = p;
- for (p = (const unsigned char *) str; p < str + len; p++) {
+ for (p = str; p < str + len; p++) {
if (strchr(ESCAPABLE_CHAR, *p)) {
FLUSH();
str++;
diff --git a/lib/graypam.h b/lib/graypam.h
index 636e4fb..f818f86 100644
--- a/lib/graypam.h
+++ b/lib/graypam.h
@@ -212,6 +212,8 @@ 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);
+int gray_env_read_tr(const char *file_name, struct gray_env **penv, char **tr);
+void gray_env_merge(struct gray_env **pa, struct gray_env **pb);
int gray_boolean_true_p(const char *value);
diff --git a/pam_ldaphome/pam_ldaphome.c b/pam_ldaphome/pam_ldaphome.c
index ba6494f..a1f467e 100644
--- a/pam_ldaphome/pam_ldaphome.c
+++ b/pam_ldaphome/pam_ldaphome.c
@@ -48,7 +48,8 @@ static char *config_file_name;
static int ldap_debug_level;
/* FIXME: This should be read from sshd_config */
static char *authorized_keys_file=".ssh/authorized_keys";
-
+static char *ldap_config_name = "/etc/ldap.conf";
+
struct pam_opt pam_opt[] = {
{ PAM_OPTSTR(debug), pam_opt_long, &debug_level },
{ PAM_OPTSTR(debug), pam_opt_const, &debug_level, { 1 } },
@@ -313,6 +314,7 @@ ldap_connect(struct gray_env *env)
int protocol = LDAP_VERSION3;
char *val;
unsigned long lval;
+ enum { tls_no, tls_yes, tls_only } tls = tls_no;
if (ldap_debug_level) {
if (ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
@@ -371,8 +373,6 @@ ldap_connect(struct gray_env *env)
val = gray_env_get(env, "tls");
if (val) {
- enum { tls_no, tls_yes, tls_only } tls;
-
if (strcmp(val, "yes") == 0)
tls = tls_yes;
else if (strcmp(val, "no") == 0)
@@ -385,28 +385,39 @@ ldap_connect(struct gray_env *env)
"assuming \"no\"");
tls = tls_no;
}
-
- if (tls != tls_no) {
- rc = ldap_start_tls_s(ld, NULL, NULL);
- if (rc != LDAP_SUCCESS) {
- char *msg = NULL;
- ldap_get_option(ld,
- LDAP_OPT_DIAGNOSTIC_MESSAGE,
- (void*)&msg);
- _pam_log(LOG_ERR,
- "ldap_start_tls failed: %s",
- ldap_err2string(rc));
- _pam_log(LOG_ERR,
- "TLS diagnostics: %s", msg);
- ldap_memfree(msg);
-
- if (tls == tls_only) {
- ldap_unbind(ld);
- return NULL;
- }
- /* try to continue anyway */
+ } else {
+ val = gray_env_get(env, "ssl");
+ if (!val)
+ tls = tls_no;
+ else if (strcmp(val, "on") == 0)
+ tls = tls_only;
+ else if (strcmp(val, "start_tls") == 0)
+ tls = tls_only;
+ else
+ tls = tls_no;
+ /* FIXME: "tls-reqcert" */
+ }
+
+ if (tls != tls_no) {
+ rc = ldap_start_tls_s(ld, NULL, NULL);
+ if (rc != LDAP_SUCCESS) {
+ char *msg = NULL;
+ ldap_get_option(ld,
+ LDAP_OPT_DIAGNOSTIC_MESSAGE,
+ (void*)&msg);
+ _pam_log(LOG_ERR,
+ "ldap_start_tls failed: %s",
+ ldap_err2string(rc));
+ _pam_log(LOG_ERR,
+ "TLS diagnostics: %s", msg);
+ ldap_memfree(msg);
+
+ if (tls == tls_only) {
+ ldap_unbind(ld);
+ return NULL;
}
-
+ /* try to continue anyway */
+ } else {
val = gray_env_get(env, "tls-cacert");
if (val) {
rc = ldap_set_option(ld,
@@ -552,7 +563,7 @@ ldap_bind(LDAP *ld, struct gray_env *env)
|| (matched && matched[0])
|| (info && info[0])
|| refs) {
- /* FIXME: Use debug output for that */
+
DEBUG(2,("ldap_bind: %s (%d)%s",
ldap_err2string(err), err, msgbuf));
@@ -1890,6 +1901,20 @@ ldaphome_main(pam_handle_t *pamh, int flags, int argc, const char **argv,
char *val;
struct passwd *pw;
+ if (val = gray_env_get(env, "ldap-config")) {
+ if (strcmp(val, "none") == 0)
+ ldap_config_name = NULL;
+ else
+ ldap_config_name = val;
+ }
+ if (ldap_config_name) {
+ static char *map[] = { "A-Z_", "a-z-" };
+ struct gray_env *tmp;
+
+ gray_env_read_tr(ldap_config_name, &tmp, map);
+ gray_env_merge(&env, &tmp);
+ }
+
if (val = gray_env_get(env, "authorized_keys"))
authorized_keys_file = val;

Return to:

Send suggestions and report system problems to the System administrator.