aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-01-28 16:42:52 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-01-28 16:42:52 +0200
commit947e0c2f8a39f072b72c7a2e5307045cb03002ac (patch)
tree47a3db70c782c076d435ea745f9e71c09b1fa635
parent399768dde3450a6184859ae0929f7debbe3521e3 (diff)
downloadpam-modules-947e0c2f8a39f072b72c7a2e5307045cb03002ac.tar.gz
pam-modules-947e0c2f8a39f072b72c7a2e5307045cb03002ac.tar.bz2
pam_ldaphome: run initrc command as user.
* examples/usergitconfig: Documentation formatting change. * lib/graypam.h (gray_2nrealloc): New function. * lib/mem.c (gray_2nrealloc): New function. * pam_fshadow/pam_fshadow.c (fgetpwent): Skip malformed entries. * pam_ldaphome/pam_ldaphome.c (runas): New finction. (run_prog): Switch to user privileges unless initrc-root is true. * NEWS: Update. * doc/pam-modules.texi: Update. * doc/pam_ldaphome.8in: Update.
-rw-r--r--NEWS7
-rw-r--r--doc/pam-modules.texi10
-rw-r--r--doc/pam_ldaphome.8in18
-rwxr-xr-xexamples/usergitconfig2
-rw-r--r--lib/graypam.h1
-rw-r--r--lib/mem.c18
-rw-r--r--pam_fshadow/pam_fshadow.c2
-rw-r--r--pam_ldaphome/pam_ldaphome.c71
8 files changed, 112 insertions, 17 deletions
diff --git a/NEWS b/NEWS
index 26acd71..7223d02 100644
--- a/NEWS
+++ b/NEWS
@@ -1,19 +1,24 @@
-pam-modules -- history of user-visible changes. 2014-07-25
+pam-modules -- history of user-visible changes. 2015-01-28
Copyright (C) 2001, 2004-2005, 2007-2012, 2014 Sergey Poznyakoff
See the end of file for copying conditions.
Please send pam-modules bug reports to <bug-pam-modules@gnu.org.ua>
Version 1.9.90 (Git)
* pam_ldaphome reads LDAP configuration from /etc/ldap.conf
This is in addition to its regular configuration file.
+* pam_ldaphome runs inirc-command with user privileges
+
+To run the command with root privileges, the configuration
+variable initrc-root must be set to true.
+
Version 1.9, 2014-05-21
* New module pam_groupmember
Tests whether the user is a member of one or more groups.
diff --git a/doc/pam-modules.texi b/doc/pam-modules.texi
index e35c3dc..a48bce6 100644
--- a/doc/pam-modules.texi
+++ b/doc/pam-modules.texi
@@ -1375,17 +1375,27 @@ files from the skeleton directory.
The user login name is passed to the command as its argument. Before
invoking, the current working directory is changed to the user home,
standard input is closed, and standard output is redirected to
standard errror.
+The command is run under the current user privileges, unless the
+variable @option{initrc-root} is set to true.
+
The command should exit with code 0 on success. If it exits with a
non-zero code, @command{pam_ldaphome} will report
@samp{PAM_SYSTEM_ERR}.
@end deffn
+@deffn {pam_ldaphome config} initrc-root @var{bool}
+When set to @code{true}, @command{initrc-command} will be run with
+root privileges. In this case, the environment variable
+@env{PAM_LDAPHOME_USER} will be initialized to the name of the
+user who is trying to log in.
+@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}.
@end deffn
@deffn {pam_ldaphome config} initrc-environ @var{env} ...
diff --git a/doc/pam_ldaphome.8in b/doc/pam_ldaphome.8in
index 3203b5c..1aa1003 100644
--- a/doc/pam_ldaphome.8in
+++ b/doc/pam_ldaphome.8in
@@ -11,13 +11,13 @@
.\" 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 PAM-Modules. If not, see <http://www.gnu.org/licenses/>.
.so config.so
-.TH PAM_LDAPHOME 8 "July 25, 2014" "PAM-MODULES" "Pam-Modules User Reference"
+.TH PAM_LDAPHOME 8 "January 28, 2015" "PAM-MODULES" "Pam-Modules User Reference"
.SH NAME
pam_ldaphome \- create and populate user home directories
.SH SYNOPSIS
.nh
.na
\fBpam_ldaphome\fR\
@@ -100,13 +100,13 @@ Controls whether TLS is desired or required. If \fIVAL\fR is
\fBno\fR (the default), TLS will not be used. If it is \fByes\fR,
the module will issue the \fIStartTLS\fR command, but will continue
anyway if it fails. Finally, if \fIVAL\fR is the word \fBonly\fR, the
use of TLS becomes mandatory, and the module will not establish LDAP
connection unless \fIStartTLS\fR succeeds.
.TP
-.BI tls-cacert " VAL"
+.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).
@@ -173,13 +173,15 @@ it runs longer than \fISECONDS\fR, it will be terminated with a
.TP
.BI initrc\-command " COMMAND"
Run \fICOMMAND\fR after populating the user home directory with
files from the skeleton directory. The user login name is passed to
\fICOMMAND\fR as its argument. Before invoking, the current working
directory is changed to the user home, standard input is closed, and
-standard output is redirected to standard errror.
+standard output is redirected to standard errror. The command is run
+with the current user privileges, unless the variable
+\fBinitrc\-root\fR is set to \fBtrue\fR.
The command should exit with code 0 on success. If it exits with a
non-zero code, PAM_SYSTEM_ERR will be reported.
.TP
\fBinitrc\-environ\fR \fIENV\fR ...
Modifies the environment of \fBinitrc\-command\fR.
@@ -216,26 +218,32 @@ value. If no such variable is present in the environment, it is
created. If \fIVALUE\fR ends with a punctuation character, this character
is removed from it before assignment.
.RE
The \fIVALUE\fR part can be enclosed in single or double quotes, in
which case the usual shell dequoting rules apply.
.TP
-.BI initrc-log " FILE"
+.BI initrc\-log " FILE"
Redirects standard output and error from the
\fBinitrc\-command\fR to \fIFILE\fR.
+.TP
+.BI initrc\-root " BOOL"
+When set to \fBtrue\fR, \fBinitrc\-command\fR will be run with
+root privileges. In this case, the environment variable
+\fBPAM_LDAPHOME_USER\fR will be initialized to the name of the
+user who is trying to log in.
.SH OPTIONS
.TP
.BI config= FILE
Read configuration from \fIFILE\fR instead of
.nh
.na
.BR \*(ET/pam_ldaphome.conf .
.ad
.hy
.TP
-\fBdebug\fR\fB=\fINUMBER\fR]
+\fBdebug\fR\fB=\fINUMBER\fR
Set debugging level (0 <= \fINUMBER\fR <= 100).
.TP
\fBwaitdebug\fR
Wait for \fIN\fR seconds before starting up. This option is intended
to facilitate attaching to the module with
.BR gdb (1).
diff --git a/examples/usergitconfig b/examples/usergitconfig
index 4748e9f..fec1a4c 100755
--- a/examples/usergitconfig
+++ b/examples/usergitconfig
@@ -124,13 +124,13 @@ Example B<.gitconfig> file:
=over 4
=item B<LDAP_CONF>
If defined, names the alternative configuration file to read.
-=item GITCONFIG_TEMPLATE
+=item B<GITCONFIG_TEMPLATE>
Name of the template file to use instead of the default B<.gitconfig>.
=back
=head1 SEE ALSO
diff --git a/lib/graypam.h b/lib/graypam.h
index e6b68aa..2548c74 100644
--- a/lib/graypam.h
+++ b/lib/graypam.h
@@ -91,12 +91,13 @@ extern jmp_buf gray_pam_jmp;
void gray_raise(const char *fmt, ...);
void *gray_malloc(size_t size);
void *gray_zalloc(size_t size);
void *gray_calloc(size_t count, size_t size);
void *gray_realloc(void *ptr, size_t size);
+void *gray_2nrealloc(void *ptr, size_t *pcount, size_t elsiz);
char *gray_strdup(const char *str);
void gray_pam_delete(char *x);
void gray_cleanup_string(pam_handle_t *pamh, void *x, int error_status);
void gray_cleanup_regex(pam_handle_t *pamh, void *x, int error_status);
void gray_make_str(pam_handle_t *pamh, const char *str, const char *name,
diff --git a/lib/mem.c b/lib/mem.c
index f90195b..2db82e1 100644
--- a/lib/mem.c
+++ b/lib/mem.c
@@ -59,12 +59,30 @@ gray_realloc(void *ptr, size_t size)
ptr = realloc(ptr, size);
if (!ptr)
gray_raise("Not enough memory");
return ptr;
}
+void *
+gray_2nrealloc(void *ptr, size_t *pcount, size_t elsiz)
+{
+ size_t count = *pcount;
+
+ if (!ptr) {
+ if (!count)
+ count = *pcount = 16;
+ return gray_calloc(count, elsiz);
+ }
+ if ((size_t)-1 / 2 / elsiz <= count)
+ gray_raise("Not enough memory");
+ count *= 2;
+ *pcount = count;
+ return gray_realloc(ptr, count * elsiz);
+}
+
+
char *
gray_strdup(const char *str)
{
char *p;
if (!str)
diff --git a/pam_fshadow/pam_fshadow.c b/pam_fshadow/pam_fshadow.c
index 02e0bfc..2094ba6 100644
--- a/pam_fshadow/pam_fshadow.c
+++ b/pam_fshadow/pam_fshadow.c
@@ -67,12 +67,14 @@ fgetpwent(FILE *fp)
return NULL;
buffer = nb;
buflen = ns;
}
if (c == '\n') {
buffer[pos++] = 0;
+ if (i != sizeof(off)/sizeof(off[0]))
+ continue;
break;
}
if (c == ':') {
buffer[pos++] = 0;
if (i < sizeof(off)/sizeof(off[0]))
off[i++] = pos;
diff --git a/pam_ldaphome/pam_ldaphome.c b/pam_ldaphome/pam_ldaphome.c
index 3bd0aa1..751a021 100644
--- a/pam_ldaphome/pam_ldaphome.c
+++ b/pam_ldaphome/pam_ldaphome.c
@@ -1918,12 +1918,57 @@ env_setup(char *envstr)
}
new_env[n] = NULL;
return new_env;
}
static int
+runas(struct passwd *pw)
+{
+ gid_t *sgv = NULL;
+ size_t sgc = 0, sgm = 0;
+ struct group *gr;
+
+ setgrent();
+ while ((gr = getgrent ())) {
+ char **p;
+ if (gr->gr_gid == pw->pw_gid)
+ continue;
+ for (p = gr->gr_mem; *p; p++) {
+ if (strcmp (*p, pw->pw_name) == 0) {
+ if (sgc == sgm)
+ sgv = gray_2nrealloc(sgv, &sgm,
+ sizeof(sgv[0]));
+ sgv[sgc++] = gr->gr_gid;
+ }
+ }
+ }
+ endgrent();
+
+ if (sgc) {
+ if (setgroups(sgc, sgv)) {
+ _pam_log(LOG_ERR, "setgroups: %s", strerror(errno));
+ free(sgv);
+ return 1;
+ }
+ free(sgv);
+ }
+
+ if (setgid(pw->pw_gid)) {
+ _pam_log(LOG_ERR, "setgid(%lu): %s",
+ (unsigned long) pw->pw_gid, strerror(errno));
+ return 1;
+ }
+ if (setuid(pw->pw_uid)) {
+ _pam_log(LOG_ERR, "setuid(%lu): %s",
+ (unsigned long) pw->pw_uid, strerror(errno));
+ return 1;
+ }
+ return 0;
+}
+
+static int
run_prog(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env,
const char *command, const char *logfile)
{
pid_t pid, rc;
int p[2];
long ttl;
@@ -1949,17 +1994,12 @@ run_prog(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env,
}
if (pid == 0) {
/* child */
char *argv[3];
- if (chdir(pw->pw_dir)) {
- _pam_log(LOG_ERR, "chdir: %s", strerror(errno));
- _exit(127);
- }
-
if (dup2(p[1], 1) == -1) {
_pam_log(LOG_ERR, "dup2: %s", strerror(errno));
_exit(127);
}
for (i = sysconf(_SC_OPEN_MAX); i >= 0; i--) {
if (i != 1)
@@ -1972,12 +2012,26 @@ run_prog(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env,
_pam_log(LOG_ERR, "open(%s): %s",
logfile, strerror(errno));
_exit(127);
}
} else
dup2(1, 2);
+
+ if (chdir(pw->pw_dir)) {
+ _pam_log(LOG_ERR, "chdir: %s", strerror(errno));
+ _exit(127);
+ }
+
+ if (gray_env_get_bool(env, "initrc-root", 0))
+ setenv("PAM_LDAPHOME_USER", pw->pw_name, 1);
+ else if (runas(pw)) {
+ _pam_log(LOG_ERR, "cannot switch to privileges of %s",
+ pw->pw_name);
+ _exit(127);
+ }
+
argv[0] = (char*) command;
argv[1] = pw->pw_name;
argv[2] = NULL;
execve(command, argv,
env_setup(gray_env_get(env, "initrc-environ")));
_exit(127);
@@ -2136,23 +2190,20 @@ 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,
- int argc,
- const char **argv)
+pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
return PAM_SUCCESS;
}
PAM_EXTERN int
pam_sm_open_session (pam_handle_t *pamh, int flags, int argc,
- const char **argv)
+ 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,

Return to:

Send suggestions and report system problems to the System administrator.