summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2015-01-28 14:42:52 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2015-01-28 14:42:52 (GMT)
commit947e0c2f8a39f072b72c7a2e5307045cb03002ac (patch) (side-by-side diff)
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.
Diffstat (more/less context) (ignore whitespace changes)
-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,4 +1,4 @@
-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.
@@ -11,6 +11,11 @@ Version 1.9.90 (Git)
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
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
@@ -1378,11 +1378,21 @@ 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}.
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
@@ -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 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
@@ -103,7 +103,7 @@ 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
@@ -176,7 +176,9 @@ 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.
@@ -219,9 +221,15 @@ is removed from it before assignment.
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
@@ -232,7 +240,7 @@ Read configuration from \fIFILE\fR instead of
.ad
.hy
.TP
-\fBdebug\fR\fB=\fINUMBER\fR]
+\fBdebug\fR\fB=\fINUMBER\fR
Set debugging level (0 <= \fINUMBER\fR <= 100).
.TP
\fBwaitdebug\fR
diff --git a/examples/usergitconfig b/examples/usergitconfig
index 4748e9f..fec1a4c 100755
--- a/examples/usergitconfig
+++ b/examples/usergitconfig
@@ -127,7 +127,7 @@ Example B<.gitconfig> file:
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>.
diff --git a/lib/graypam.h b/lib/graypam.h
index e6b68aa..2548c74 100644
--- a/lib/graypam.h
+++ b/lib/graypam.h
@@ -94,6 +94,7 @@ 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);
diff --git a/lib/mem.c b/lib/mem.c
index f90195b..2db82e1 100644
--- a/lib/mem.c
+++ b/lib/mem.c
@@ -62,6 +62,24 @@ gray_realloc(void *ptr, size_t size)
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)
{
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
@@ -70,6 +70,8 @@ fgetpwent(FILE *fp)
}
if (c == '\n') {
buffer[pos++] = 0;
+ if (i != sizeof(off)/sizeof(off[0]))
+ continue;
break;
}
if (c == ':') {
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
@@ -1921,6 +1921,51 @@ env_setup(char *envstr)
}
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)
{
@@ -1952,11 +1997,6 @@ run_prog(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env,
/* 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);
@@ -1975,6 +2015,20 @@ run_prog(pam_handle_t *pamh, struct passwd *pw, struct gray_env *env,
}
} 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;
@@ -2139,17 +2193,14 @@ pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
}
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__);
}

Return to:

Send suggestions and report system problems to the System administrator.