diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-07-25 15:09:33 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-07-25 15:37:28 +0300 |
commit | b4a27a9c7afc21d7a4895cddc5c182c3349f1f11 (patch) | |
tree | 9808605942a1c52af52fcb9c3cdbe14925bd370b | |
parent | c1059e03983d704ea79cf97d9cffb2cbaa79bcae (diff) | |
download | pam-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.
-rw-r--r-- | doc/pam-modules.texi | 179 | ||||
-rw-r--r-- | doc/pam_ldaphome.8in | 26 | ||||
-rw-r--r-- | lib/env.c | 58 | ||||
-rw-r--r-- | lib/escape.c | 6 | ||||
-rw-r--r-- | lib/graypam.h | 2 | ||||
-rw-r--r-- | pam_ldaphome/pam_ldaphome.c | 35 |
6 files changed, 227 insertions, 79 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 @@ -45,6 +45,20 @@ 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. .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 .TP @@ -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. @@ -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 @@ -19,13 +19,13 @@ void 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,6 +48,7 @@ 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 }, @@ -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,6 +385,18 @@ ldap_connect(struct gray_env *env) "assuming \"no\""); tls = tls_no; } + } 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); @@ -405,8 +417,7 @@ ldap_connect(struct gray_env *env) 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; |