summaryrefslogtreecommitdiff
path: root/Linux-PAM/modules
diff options
context:
space:
mode:
Diffstat (limited to 'Linux-PAM/modules')
-rw-r--r--Linux-PAM/modules/Makefile4
-rw-r--r--Linux-PAM/modules/Simple.Rules18
-rw-r--r--Linux-PAM/modules/dont_makefile2
-rwxr-xr-xLinux-PAM/modules/download-all2
-rw-r--r--Linux-PAM/modules/pam_access/Makefile5
-rw-r--r--Linux-PAM/modules/pam_access/access.conf7
-rw-r--r--Linux-PAM/modules/pam_access/pam_access.c149
-rw-r--r--Linux-PAM/modules/pam_cracklib/Makefile2
-rw-r--r--Linux-PAM/modules/pam_cracklib/pam_cracklib.c55
-rw-r--r--Linux-PAM/modules/pam_debug/Makefile2
-rw-r--r--Linux-PAM/modules/pam_debug/README2
-rw-r--r--Linux-PAM/modules/pam_debug/pam_debug.c6
-rw-r--r--Linux-PAM/modules/pam_deny/Makefile2
-rw-r--r--Linux-PAM/modules/pam_deny/README2
-rw-r--r--Linux-PAM/modules/pam_deny/pam_deny.c2
-rw-r--r--Linux-PAM/modules/pam_env/Makefile2
-rw-r--r--Linux-PAM/modules/pam_env/README6
-rw-r--r--Linux-PAM/modules/pam_env/pam_env.c25
-rw-r--r--Linux-PAM/modules/pam_env/pam_env.conf-example10
-rw-r--r--Linux-PAM/modules/pam_filter/Makefile2
-rw-r--r--Linux-PAM/modules/pam_filter/README2
-rw-r--r--Linux-PAM/modules/pam_filter/include/pam_filter.h2
-rw-r--r--Linux-PAM/modules/pam_filter/pam_filter.c41
-rw-r--r--Linux-PAM/modules/pam_filter/upperLOWER/Makefile9
-rw-r--r--Linux-PAM/modules/pam_filter/upperLOWER/upperLOWER.c17
-rw-r--r--Linux-PAM/modules/pam_ftp/Makefile2
-rw-r--r--Linux-PAM/modules/pam_ftp/pam_ftp.c6
-rw-r--r--Linux-PAM/modules/pam_group/Makefile4
-rw-r--r--Linux-PAM/modules/pam_group/pam_group.c29
-rw-r--r--Linux-PAM/modules/pam_issue/Makefile2
-rw-r--r--Linux-PAM/modules/pam_issue/pam_issue.c37
-rw-r--r--Linux-PAM/modules/pam_lastlog/Makefile2
-rw-r--r--Linux-PAM/modules/pam_lastlog/pam_lastlog.c24
-rw-r--r--Linux-PAM/modules/pam_limits/Makefile8
-rw-r--r--Linux-PAM/modules/pam_limits/README3
-rw-r--r--Linux-PAM/modules/pam_limits/limits.skel2
-rw-r--r--Linux-PAM/modules/pam_limits/pam_limits.c147
-rw-r--r--Linux-PAM/modules/pam_listfile/Makefile2
-rw-r--r--Linux-PAM/modules/pam_listfile/pam_listfile.c90
-rw-r--r--Linux-PAM/modules/pam_localuser/Makefile14
-rw-r--r--Linux-PAM/modules/pam_localuser/README17
-rw-r--r--Linux-PAM/modules/pam_localuser/pam_localuser.836
-rw-r--r--Linux-PAM/modules/pam_localuser/pam_localuser.c159
-rw-r--r--Linux-PAM/modules/pam_mail/Makefile2
-rw-r--r--Linux-PAM/modules/pam_mail/pam_mail.c25
-rw-r--r--Linux-PAM/modules/pam_mkhomedir/Makefile2
-rw-r--r--Linux-PAM/modules/pam_mkhomedir/README25
-rw-r--r--Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c194
-rw-r--r--Linux-PAM/modules/pam_motd/Makefile2
-rw-r--r--Linux-PAM/modules/pam_motd/pam_motd.c40
-rw-r--r--Linux-PAM/modules/pam_nologin/Makefile2
-rw-r--r--Linux-PAM/modules/pam_nologin/README2
-rw-r--r--Linux-PAM/modules/pam_nologin/pam_nologin.c35
-rw-r--r--Linux-PAM/modules/pam_permit/Makefile2
-rw-r--r--Linux-PAM/modules/pam_permit/README2
-rw-r--r--Linux-PAM/modules/pam_permit/pam_permit.c6
-rw-r--r--Linux-PAM/modules/pam_pwdb/BUGS2
-rw-r--r--Linux-PAM/modules/pam_pwdb/CHANGELOG2
-rw-r--r--Linux-PAM/modules/pam_pwdb/Makefile7
-rw-r--r--Linux-PAM/modules/pam_pwdb/TODO2
-rw-r--r--Linux-PAM/modules/pam_pwdb/md5.c2
-rw-r--r--Linux-PAM/modules/pam_pwdb/md5_crypt.c2
-rw-r--r--Linux-PAM/modules/pam_pwdb/pam_pwdb.c4
-rw-r--r--Linux-PAM/modules/pam_pwdb/pam_unix_acct.-c4
-rw-r--r--Linux-PAM/modules/pam_pwdb/pam_unix_auth.-c4
-rw-r--r--Linux-PAM/modules/pam_pwdb/pam_unix_passwd.-c4
-rw-r--r--Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c2
-rw-r--r--Linux-PAM/modules/pam_pwdb/pam_unix_sess.-c4
-rw-r--r--Linux-PAM/modules/pam_pwdb/pwdb_chkpwd.c2
-rw-r--r--Linux-PAM/modules/pam_pwdb/support.-c28
-rw-r--r--Linux-PAM/modules/pam_radius/pam_radius.h2
-rw-r--r--Linux-PAM/modules/pam_rhosts/Makefile2
-rw-r--r--Linux-PAM/modules/pam_rhosts/pam_rhosts_auth.c51
-rw-r--r--Linux-PAM/modules/pam_rootok/Makefile2
-rw-r--r--Linux-PAM/modules/pam_rootok/README2
-rw-r--r--Linux-PAM/modules/pam_rootok/pam_rootok.c2
-rw-r--r--Linux-PAM/modules/pam_securetty/Makefile2
-rw-r--r--Linux-PAM/modules/pam_securetty/pam_securetty.c127
-rw-r--r--Linux-PAM/modules/pam_shells/Makefile2
-rw-r--r--Linux-PAM/modules/pam_shells/README3
-rw-r--r--Linux-PAM/modules/pam_shells/pam_shells.c137
-rw-r--r--Linux-PAM/modules/pam_stress/Makefile2
-rw-r--r--Linux-PAM/modules/pam_stress/README2
-rw-r--r--Linux-PAM/modules/pam_stress/pam_stress.c74
-rw-r--r--Linux-PAM/modules/pam_succeed_if/Makefile16
-rw-r--r--Linux-PAM/modules/pam_succeed_if/README68
-rw-r--r--Linux-PAM/modules/pam_succeed_if/pam_succeed_if.837
-rw-r--r--Linux-PAM/modules/pam_succeed_if/pam_succeed_if.c470
-rw-r--r--Linux-PAM/modules/pam_tally/Makefile12
-rw-r--r--Linux-PAM/modules/pam_tally/README87
-rw-r--r--Linux-PAM/modules/pam_tally/faillog.h2
-rw-r--r--Linux-PAM/modules/pam_tally/pam_tally.c579
-rw-r--r--Linux-PAM/modules/pam_time/Makefile2
-rw-r--r--Linux-PAM/modules/pam_time/README2
-rw-r--r--Linux-PAM/modules/pam_time/pam_time.c8
-rw-r--r--Linux-PAM/modules/pam_unix/CHANGELOG2
-rw-r--r--Linux-PAM/modules/pam_unix/Makefile38
-rw-r--r--Linux-PAM/modules/pam_unix/README2
-rw-r--r--Linux-PAM/modules/pam_unix/bigcrypt_main.c18
-rw-r--r--Linux-PAM/modules/pam_unix/md5.c2
-rw-r--r--Linux-PAM/modules/pam_unix/md5_crypt.c2
-rw-r--r--Linux-PAM/modules/pam_unix/pam_unix_acct.c53
-rw-r--r--Linux-PAM/modules/pam_unix/pam_unix_auth.c13
-rw-r--r--Linux-PAM/modules/pam_unix/pam_unix_passwd.c329
-rw-r--r--Linux-PAM/modules/pam_unix/pam_unix_sess.c21
-rw-r--r--Linux-PAM/modules/pam_unix/support.c399
-rw-r--r--Linux-PAM/modules/pam_unix/support.h21
-rw-r--r--Linux-PAM/modules/pam_unix/unix_chkpwd.c53
-rw-r--r--Linux-PAM/modules/pam_userdb/Makefile6
-rw-r--r--Linux-PAM/modules/pam_userdb/README39
-rw-r--r--Linux-PAM/modules/pam_userdb/conv.c2
-rw-r--r--Linux-PAM/modules/pam_userdb/create.pl4
-rw-r--r--Linux-PAM/modules/pam_userdb/pam_userdb.c291
-rw-r--r--Linux-PAM/modules/pam_userdb/pam_userdb.h5
-rw-r--r--Linux-PAM/modules/pam_warn/Makefile2
-rw-r--r--Linux-PAM/modules/pam_warn/README2
-rw-r--r--Linux-PAM/modules/pam_warn/pam_warn.c2
-rw-r--r--Linux-PAM/modules/pam_wheel/Makefile2
-rw-r--r--Linux-PAM/modules/pam_wheel/README26
-rw-r--r--Linux-PAM/modules/pam_wheel/pam_wheel.c269
-rw-r--r--Linux-PAM/modules/pam_xauth/Makefile12
-rw-r--r--Linux-PAM/modules/pam_xauth/README41
-rw-r--r--Linux-PAM/modules/pam_xauth/pam_xauth.882
-rw-r--r--Linux-PAM/modules/pam_xauth/pam_xauth.c641
-rw-r--r--Linux-PAM/modules/pammodutil/Makefile6
-rw-r--r--Linux-PAM/modules/pammodutil/README2
-rw-r--r--Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h37
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_cleanup.c2
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getgrgid.c150
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getgrnam.c139
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getlogin.c72
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getpwnam.c71
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getpwuid.c90
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_getspnam.c139
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_ingroup.c121
-rw-r--r--Linux-PAM/modules/pammodutil/modutil_ioloop.c52
-rw-r--r--Linux-PAM/modules/pammodutil/pammodutil.h4
137 files changed, 4924 insertions, 1401 deletions
diff --git a/Linux-PAM/modules/Makefile b/Linux-PAM/modules/Makefile
index 96b3a636..58be5a24 100644
--- a/Linux-PAM/modules/Makefile
+++ b/Linux-PAM/modules/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1.1.2 2002/09/15 20:08:43 hartmans Exp $
+# $Id: Makefile,v 1.4 2004/09/28 13:48:47 kukuk Exp $
#
# Makefile
#
@@ -8,7 +8,7 @@
include ../Make.Rules
-MODDIRS=$(shell /bin/ls -d pam_*)
+MODDIRS=$(shell /bin/ls -d pam_*/Makefile | cut -f1 -d/)
all:
@echo building the static modutil library
diff --git a/Linux-PAM/modules/Simple.Rules b/Linux-PAM/modules/Simple.Rules
index bbbf3e50..57b582de 100644
--- a/Linux-PAM/modules/Simple.Rules
+++ b/Linux-PAM/modules/Simple.Rules
@@ -1,4 +1,4 @@
-# $Id: Simple.Rules,v 1.1.1.2 2002/09/15 20:08:43 hartmans Exp $
+# $Id: Simple.Rules,v 1.7 2004/09/28 13:48:47 kukuk Exp $
#
# For simple modules with no significant dependencies, set $(TITLE)
# and include this file.
@@ -13,13 +13,15 @@
# $(MODULE_SIMPLE_EXTRAFILES) - other files to build (no .c suffix)
#
+-include ../Make.Rules
+
LIBFILES = $(TITLE) $(MODULE_SIMPLE_EXTRAFILES)
LIBSRC = $(addsuffix .c,$(LIBFILES))
LIBOBJ = $(addsuffix .o,$(LIBFILES))
LIBOBJD = $(addprefix dynamic/,$(LIBOBJ))
LIBOBJS = $(addprefix static/,$(LIBOBJ))
-LINK_PAMMODUTILS = -L../pammodutil -lpammodutil
+LINK_PAMMODUTILS = -L../pammodutil -lpammodutil -L../../libpam -lpam
INCLUDE_PAMMODUTILS = -I../pammodutil/include
ifdef DYNAMIC
@@ -77,6 +79,18 @@ install: all
ifdef DYNAMIC
$(INSTALL) -m $(SHLIBMODE) $(LIBSHARED) $(FAKEROOT)$(SECUREDIR)
endif
+ifdef MAN3
+ test -d $(FAKEROOT)$(mandir)/man3 || $(MKDIR) $(FAKEROOT)$(mandir)/man3
+ $(INSTALL) -m $(MANMODE) $(MAN3) $(FAKEROOT)$(mandir)/man3/
+endif
+ifdef MAN5
+ test -d $(FAKEROOT)$(mandir)/man5 || $(MKDIR) $(FAKEROOT)$(mandir)/man5
+ $(INSTALL) -m $(MANMODE) $(MAN5) $(FAKEROOT)$(mandir)/man5/
+endif
+ifdef MAN8
+ test -d $(FAKEROOT)$(mandir)/man8 || $(MKDIR) $(FAKEROOT)$(mandir)/man8
+ $(INSTALL) -m $(MANMODE) $(MAN8) $(FAKEROOT)$(mandir)/man8/
+endif
$(MODULE_SIMPLE_INSTALL)
remove:
diff --git a/Linux-PAM/modules/dont_makefile b/Linux-PAM/modules/dont_makefile
index b49e9e7a..48307f02 100644
--- a/Linux-PAM/modules/dont_makefile
+++ b/Linux-PAM/modules/dont_makefile
@@ -1,5 +1,5 @@
#########################################################################
-# $Id: dont_makefile,v 1.1.1.1 2001/04/29 04:17:16 hartmans Exp $
+# $Id: dont_makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $
#########################################################################
# This is a makefile that does nothing. It is designed to be included
# by module Makefile-s when they are not compatable with the local
diff --git a/Linux-PAM/modules/download-all b/Linux-PAM/modules/download-all
index 451b3c51..9b6cf655 100755
--- a/Linux-PAM/modules/download-all
+++ b/Linux-PAM/modules/download-all
@@ -1,6 +1,6 @@
#!/bin/sh
#
-# $Id: download-all,v 1.1.1.1 2001/04/29 04:17:16 hartmans Exp $
+# $Id: download-all,v 1.1.1.1 2000/06/20 22:11:29 agmorgan Exp $
#
cat <<EOT
For a number of reasons it is not practical for Linux-PAM to be
diff --git a/Linux-PAM/modules/pam_access/Makefile b/Linux-PAM/modules/pam_access/Makefile
index 5f8574ab..d8a71ee5 100644
--- a/Linux-PAM/modules/pam_access/Makefile
+++ b/Linux-PAM/modules/pam_access/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:16 hartmans Exp $
+# $Id: Makefile,v 1.3 2003/07/13 18:41:04 vorlon Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
@@ -10,6 +10,9 @@ include ../../Make.Rules
TITLE=pam_access
LOCAL_CONFILE=./access.conf
INSTALLED_CONFILE=$(SCONFIGD)/access.conf
+ifeq ($(HAVE_LIBNSL),yes)
+MODULE_SIMPLE_EXTRALIBS=-lnsl
+endif
DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\"
CFLAGS += $(DEFS)
diff --git a/Linux-PAM/modules/pam_access/access.conf b/Linux-PAM/modules/pam_access/access.conf
index dbaadf67..cec2be0c 100644
--- a/Linux-PAM/modules/pam_access/access.conf
+++ b/Linux-PAM/modules/pam_access/access.conf
@@ -40,8 +40,15 @@
# logged-in user. Both the user's primary group is matched, as well as
# groups in which users are explicitly listed.
#
+# TTY NAMES: Must be in the form returned by ttyname(3) less the initial
+# "/dev" (e.g. tty1 or vc/1)
+#
##############################################################################
#
+# Disallow non-root logins on tty1
+#
+#-:ALL EXCEPT root:tty1
+#
# Disallow console logins to all but a few accounts.
#
#-:ALL EXCEPT wheel shutdown sync:LOCAL
diff --git a/Linux-PAM/modules/pam_access/pam_access.c b/Linux-PAM/modules/pam_access/pam_access.c
index 4005c93b..4f6cf574 100644
--- a/Linux-PAM/modules/pam_access/pam_access.c
+++ b/Linux-PAM/modules/pam_access/pam_access.c
@@ -5,23 +5,23 @@
* (I took login_access from logdaemon-5.6 and converted it to PAM
* using parts of pam_time code.)
*
- ************************************************************************
+ ************************************************************************
* Copyright message from logdaemon-5.6 (original file name DISCLAIMER)
- ************************************************************************
- * Copyright 1995 by Wietse Venema. All rights reserved. Individual files
- * may be covered by other copyrights (as noted in the file itself.)
- *
- * This material was originally written and compiled by Wietse Venema at
- * Eindhoven University of Technology, The Netherlands, in 1990, 1991,
- * 1992, 1993, 1994 and 1995.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this entire copyright notice is duplicated in all such
- * copies.
- *
- * This software is provided "as is" and without any expressed or implied
- * warranties, including, without limitation, the implied warranties of
- * merchantibility and fitness for any particular purpose.
+ ************************************************************************
+ * Copyright 1995 by Wietse Venema. All rights reserved. Individual files
+ * may be covered by other copyrights (as noted in the file itself.)
+ *
+ * This material was originally written and compiled by Wietse Venema at
+ * Eindhoven University of Technology, The Netherlands, in 1990, 1991,
+ * 1992, 1993, 1994 and 1995.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this entire copyright notice is duplicated in all such
+ * copies.
+ *
+ * This software is provided "as is" and without any expressed or implied
+ * warranties, including, without limitation, the implied warranties of
+ * merchantibility and fitness for any particular purpose.
*************************************************************************
*/
@@ -41,6 +41,7 @@
#include <errno.h>
#include <ctype.h>
#include <sys/utsname.h>
+#include <rpcsvc/ypclnt.h>
#ifndef BROKEN_NETWORK_MATCH
# include <netdb.h>
@@ -58,8 +59,7 @@
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
-
-int strcasecmp(const char *s1, const char *s2);
+#include <security/_pam_modutil.h>
/* login_access.c from logdaemon-5.6 with several changes by A.Nogin: */
@@ -68,7 +68,7 @@ int strcasecmp(const char *s1, const char *s2);
* control based on login names and on host (or domain) names, internet
* addresses (or network numbers), or on terminal line names in case of
* non-networked logins. Diagnostics are reported through syslog(3).
- *
+ *
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*/
@@ -140,26 +140,27 @@ static int parse_args(struct login_info *loginfo, int argc, const char **argv)
, loginfo->service, 11 + argv[i]);
return 0;
}
-
+
} else {
_log_err("unrecognized option [%s]", argv[i]);
}
}
-
+
return 1; /* OK */
}
-typedef int match_func (char *, struct login_info *);
+typedef int match_func (pam_handle_t *, char *, struct login_info *);
-static int list_match (char *, struct login_info *,
- match_func *);
-static int user_match (char *, struct login_info *);
-static int from_match (char *, struct login_info *);
-static int string_match (char *, char *);
+static int list_match (pam_handle_t *, char *, struct login_info *,
+ match_func *);
+static int user_match (pam_handle_t *, char *, struct login_info *);
+static int from_match (pam_handle_t *, char *, struct login_info *);
+static int string_match (pam_handle_t *, char *, char *);
/* login_access - match username/group and host/tty with access control file */
-static int login_access(struct login_info *item)
+static int
+login_access (pam_handle_t *pamh, struct login_info *item)
{
FILE *fp;
char line[BUFSIZ];
@@ -193,10 +194,11 @@ static int login_access(struct login_info *item)
line[end] = 0; /* strip trailing whitespace */
if (line[0] == 0) /* skip blank lines */
continue;
+
+ /* Allow trailing: in last field fo froms */
if (!(perm = strtok(line, fs))
|| !(users = strtok((char *) 0, fs))
- || !(froms = strtok((char *) 0, fs))
- || strtok((char *) 0, fs)) {
+ || !(froms = strtok((char *) 0, fs))) {
_log_err("%s: line %d: bad field count",
item->config_file, lineno);
continue;
@@ -206,19 +208,21 @@ static int login_access(struct login_info *item)
item->config_file, lineno);
continue;
}
- match = (list_match(froms, item, from_match)
- && list_match(users, item, user_match));
+ match = (list_match(pamh, froms, item, from_match)
+ && list_match(pamh, users, item, user_match));
}
(void) fclose(fp);
} else if (errno != ENOENT) {
_log_err("cannot open %s: %m", item->config_file);
+ return NO;
}
return (match == 0 || (line[0] == '+'));
}
/* list_match - match an item against a list of tokens with exceptions */
-static int list_match(char *list, struct login_info *item, match_func *match_fn)
+static int list_match(pam_handle_t *pamh,
+ char *list, struct login_info *item, match_func *match_fn)
{
char *tok;
int match = NO;
@@ -233,7 +237,7 @@ static int list_match(char *list, struct login_info *item, match_func *match_fn)
for (tok = strtok(list, sep); tok != 0; tok = strtok((char *) 0, sep)) {
if (strcasecmp(tok, "EXCEPT") == 0) /* EXCEPT: give up */
break;
- if ((match = (*match_fn) (tok, item))) /* YES */
+ if ((match = (*match_fn) (pamh, tok, item))) /* YES */
break;
}
/* Process exceptions to matches. */
@@ -241,7 +245,7 @@ static int list_match(char *list, struct login_info *item, match_func *match_fn)
if (match != NO) {
while ((tok = strtok((char *) 0, sep)) && strcasecmp(tok, "EXCEPT"))
/* VOID */ ;
- if (tok == 0 || list_match((char *) 0, item, match_fn) == NO)
+ if (tok == 0 || list_match(pamh, (char *) 0, item, match_fn) == NO)
return (match);
}
return (NO);
@@ -253,35 +257,30 @@ static char * myhostname(void)
{
static char name[MAXHOSTNAMELEN + 1];
- gethostname(name, MAXHOSTNAMELEN);
- name[MAXHOSTNAMELEN] = 0;
- return (name);
+ if (gethostname(name, MAXHOSTNAMELEN) == 0) {
+ name[MAXHOSTNAMELEN] = 0;
+ return (name);
+ }
+ return NULL;
}
/* netgroup_match - match group against machine or user */
static int netgroup_match(char *group, char *machine, char *user)
{
-#ifdef NIS
- static char *mydomain = 0;
+ static char *mydomain = NULL;
if (mydomain == 0)
yp_get_default_domain(&mydomain);
return (innetgr(group, machine, user, mydomain));
-#else
- _log_err("NIS netgroup support not configured");
- return (NO);
-#endif
}
/* user_match - match a username against one token */
-static int user_match(char *tok, struct login_info *item)
+static int user_match(pam_handle_t *pamh, char *tok, struct login_info *item)
{
char *string = item->user->pw_name;
struct login_info fake_item;
- struct group *group;
- int i;
char *at;
/*
@@ -294,24 +293,24 @@ static int user_match(char *tok, struct login_info *item)
if ((at = strchr(tok + 1, '@')) != 0) { /* split user@host pattern */
*at = 0;
fake_item.from = myhostname();
- return (user_match(tok, item) && from_match(at + 1, &fake_item));
- } else if (tok[0] == '@') { /* netgroup */
+ if (fake_item.from == NULL)
+ return NO;
+ return (user_match (pamh, tok, item) && from_match (pamh, at + 1, &fake_item));
+ } else if (tok[0] == '@') /* netgroup */
return (netgroup_match(tok + 1, (char *) 0, string));
- } else if (string_match(tok, string)) { /* ALL or exact match */
- return (YES);
- } else if ((group = getgrnam(tok))) { /* try group membership */
- if (item->user->pw_gid == group->gr_gid)
- return (YES);
- for (i = 0; group->gr_mem[i]; i++)
- if (strcasecmp(string, group->gr_mem[i]) == 0)
- return (YES);
- }
- return (NO);
+ else if (string_match (pamh, tok, string)) /* ALL or exact match */
+ return YES;
+ else if (_pammodutil_user_in_group_nam_nam (pamh, item->user->pw_name, tok))
+ /* try group membership */
+ return YES;
+
+ return NO;
}
/* from_match - match a host or tty against a list of tokens */
-static int from_match(char *tok, struct login_info *item)
+static int
+from_match (pam_handle_t *pamh, char *tok, struct login_info *item)
{
char *string = item->from;
int tok_len;
@@ -328,9 +327,9 @@ static int from_match(char *tok, struct login_info *item)
if (tok[0] == '@') { /* netgroup */
return (netgroup_match(tok + 1, string, (char *) 0));
- } else if (string_match(tok, string)) { /* ALL or exact match */
- return (YES);
- } else if (tok[0] == '.') { /* domain: match last fields */
+ } else if (string_match (pamh, tok, string)) /* ALL or exact match */
+ return YES;
+ else if (tok[0] == '.') { /* domain: match last fields */
if ((str_len = strlen(string)) > (tok_len = strlen(tok))
&& strcasecmp(tok, string + str_len - tok_len) == 0)
return (YES);
@@ -374,7 +373,8 @@ static int from_match(char *tok, struct login_info *item)
/* string_match - match a string against one token */
-static int string_match(char *tok, char *string)
+static int
+string_match (pam_handle_t *pamh, char *tok, char *string)
{
/*
@@ -390,14 +390,6 @@ static int string_match(char *tok, char *string)
return (NO);
}
-/* end of login_access.c */
-
-int strcasecmp(const char *s1, const char *s2)
-{
- while ((toupper(*s1)==toupper(*s2)) && (*s1) && (*s2)) {s1++; s2++;}
- return(toupper(*s1)-toupper(*s2));
-}
-
/* --- public account management functions --- */
PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
@@ -447,13 +439,15 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
return PAM_ABORT;
}
}
- if (strncmp("/dev/",from,5) == 0) { /* strip leading /dev/ */
- from += 5;
- }
+ if (from[0] == '/') { /* full path */
+ from++;
+ from = strchr(from, '/');
+ from++;
+ }
}
- if ((user_pw=getpwnam(user))==NULL) return (PAM_USER_UNKNOWN);
+ if ((user_pw=_pammodutil_getpwnam(pamh, user))==NULL) return (PAM_USER_UNKNOWN);
/*
* Bundle up the arguments to avoid unnecessary clumsiness later on.
@@ -470,7 +464,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc
return PAM_ABORT;
}
- if (login_access(&loginfo)) {
+ if (login_access(pamh, &loginfo)) {
return (PAM_SUCCESS);
} else {
_log_err("access denied for user `%s' from `%s'",user,from);
@@ -494,4 +488,3 @@ struct pam_module _pam_access_modstruct = {
NULL
};
#endif
-
diff --git a/Linux-PAM/modules/pam_cracklib/Makefile b/Linux-PAM/modules/pam_cracklib/Makefile
index 9e8f69aa..371ac0a8 100644
--- a/Linux-PAM/modules/pam_cracklib/Makefile
+++ b/Linux-PAM/modules/pam_cracklib/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:17 hartmans Exp $
+# $Id: Makefile,v 1.3 2001/02/10 22:15:23 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_cracklib/pam_cracklib.c b/Linux-PAM/modules/pam_cracklib/pam_cracklib.c
index fa415e32..8f3e4c42 100644
--- a/Linux-PAM/modules/pam_cracklib/pam_cracklib.c
+++ b/Linux-PAM/modules/pam_cracklib/pam_cracklib.c
@@ -1,6 +1,6 @@
/*
* pam_cracklib module
- * $Id: pam_cracklib.c,v 1.1.1.2 2002/09/15 20:08:45 hartmans Exp $
+ * $Id: pam_cracklib.c,v 1.9 2004/09/15 12:06:17 kukuk Exp $
*/
/*
@@ -77,7 +77,7 @@ extern char *FascistCheck(char *pw, const char *dictpath);
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
-#ifndef LINUX_PAM
+#ifndef LINUX_PAM
#include <security/pam_appl.h>
#endif /* LINUX_PAM */
@@ -186,11 +186,11 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs,
struct pam_response **response)
{
int retval;
- struct pam_conv *conv;
+ struct pam_conv *conv = NULL;
- retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
+ retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
- if ( retval == PAM_SUCCESS ) {
+ if ( retval == PAM_SUCCESS && conv ) {
retval = conv->conv(nargs, (const struct pam_message **)message,
response, conv->appdata_ptr);
if (retval != PAM_SUCCESS && (ctrl && PAM_DEBUG_ARG)) {
@@ -199,7 +199,9 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs,
}
} else {
_pam_log(LOG_ERR, "couldn't obtain coversation function [%s]",
- pam_strerror(pamh, retval));
+ pam_strerror(pamh, retval));
+ if ( retval == PAM_SUCCESS )
+ retval = PAM_BAD_ITEM; /* conv was NULL */
}
return retval; /* propagate error status */
@@ -258,12 +260,12 @@ static int distdifferent(const char *old, const char *new, int i, int j)
{
char c, d;
- if ((i == 0) || (strlen(old) <= i)) {
+ if ((i == 0) || (strlen(old) < i)) {
c = 0;
} else {
c = old[i - 1];
}
- if ((j == 0) || (strlen(new) <= i)) {
+ if ((j == 0) || (strlen(new) < j)) {
d = 0;
} else {
d = new[j - 1];
@@ -389,17 +391,17 @@ static int simple(struct cracklib_options *opt,
size -= digits;
else if (digits < opt->dig_credit * -1)
return 1;
-
+
if (opt->up_credit >= 0)
size -= uppers;
else if (uppers < opt->up_credit * -1)
return 1;
-
+
if (opt->low_credit >= 0)
size -= lowers;
else if (lowers < opt->low_credit * -1)
return 1;
-
+
if (opt->oth_credit >= 0)
size -= others;
else if (others < opt->oth_credit * -1)
@@ -507,7 +509,7 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh,
const char *msg = NULL;
const char *user;
int retval;
-
+
if (pass_new == NULL || (pass_old && !strcmp(pass_old,pass_new))) {
if (ctrl && PAM_DEBUG_ARG)
_pam_log(LOG_DEBUG, "bad authentication token");
@@ -524,7 +526,7 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh,
msg = password_check(opt, pass_old,pass_new);
if (!msg) {
retval = pam_get_item(pamh, PAM_USER, (const void **)&user);
- if (retval != PAM_SUCCESS) {
+ if (retval != PAM_SUCCESS || user == NULL) {
if (ctrl & PAM_DEBUG_ARG) {
_pam_log(LOG_ERR,"Can not get username");
return PAM_AUTHTOK_ERR;
@@ -535,7 +537,7 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh,
if (msg) {
char remark[BUFSIZ];
-
+
memset(remark,0,sizeof(remark));
snprintf(remark,sizeof(remark),"BAD PASSWORD: %s",msg);
if (ctrl && PAM_DEBUG_ARG)
@@ -543,12 +545,12 @@ static int _pam_unix_approve_pass(pam_handle_t *pamh,
msg);
make_remark(pamh, ctrl, PAM_ERROR_MSG, remark);
return PAM_AUTHTOK_ERR;
- };
+ };
return PAM_SUCCESS;
-
+
}
-/* The Main Thing (by Cristian Gafton, CEO at this module :-)
+/* The Main Thing (by Cristian Gafton, CEO at this module :-)
* (stolen from http://home.netscape.com)
*/
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
@@ -559,6 +561,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
D(("called."));
+ memset(&options, 0, sizeof(options));
options.retry_times = CO_RETRY_TIMES;
options.diff_ok = CO_DIFF_OK;
options.diff_ignore = CO_DIFF_IGNORE;
@@ -574,7 +577,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
ctrl = _pam_parse(&options, argc, argv);
if (flags & PAM_PRELIM_CHECK) {
- /* Check for passwd dictionary */
+ /* Check for passwd dictionary */
struct stat st;
char buf[sizeof(CRACKLIB_DICTPATH)+10];
@@ -591,7 +594,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
CRACKLIB_DICTPATH);
return PAM_ABORT;
}
-
+
/* Not reached */
return PAM_SERVICE_ERR;
@@ -613,12 +616,12 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
retval = PAM_SUCCESS;
}
- do {
+ do {
/*
* make sure nothing inappropriate gets returned
*/
token1 = token2 = NULL;
-
+
if (!options.retry_times) {
D(("returning %s because maxtries reached",
pam_strerror(pamh, retval)));
@@ -628,7 +631,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
/* Planned modus operandi:
* Get a passwd.
* Verify it against cracklib.
- * If okay get it a second time.
+ * If okay get it a second time.
* Check to be the same with the first one.
* set PAM_AUTHTOK and return
*/
@@ -691,7 +694,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
{
char *crack_msg;
char remark[BUFSIZ];
-
+
bzero(remark,sizeof(remark));
D(("against cracklib"));
if ((crack_msg = FascistCheck(token1, cracklib_dictpath))) {
@@ -779,7 +782,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
retval = PAM_AUTHTOK_RECOVER_ERR;
continue;
}
-
+
/* Yes, the password was typed correct twice
* we store this password as an item
*/
@@ -804,7 +807,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
return PAM_SUCCESS;
}
}
-
+
} while (options.retry_times--);
} else {
@@ -814,7 +817,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
}
/* Not reached */
- return PAM_SERVICE_ERR;
+ return PAM_SERVICE_ERR;
}
diff --git a/Linux-PAM/modules/pam_debug/Makefile b/Linux-PAM/modules/pam_debug/Makefile
index bb759918..56e9a14e 100644
--- a/Linux-PAM/modules/pam_debug/Makefile
+++ b/Linux-PAM/modules/pam_debug/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2002/09/15 20:08:45 hartmans Exp $
+# $Id: Makefile,v 1.1 2001/10/10 05:00:11 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_debug/README b/Linux-PAM/modules/pam_debug/README
index c1dad0f8..85401651 100644
--- a/Linux-PAM/modules/pam_debug/README
+++ b/Linux-PAM/modules/pam_debug/README
@@ -1,4 +1,4 @@
-# $Id: README,v 1.1.1.1 2002/09/15 20:08:45 hartmans Exp $
+# $Id: README,v 1.1 2001/10/10 05:00:11 agmorgan Exp $
#
This module returns what its module arguments tell it to return. It
diff --git a/Linux-PAM/modules/pam_debug/pam_debug.c b/Linux-PAM/modules/pam_debug/pam_debug.c
index 6226c829..819cd651 100644
--- a/Linux-PAM/modules/pam_debug/pam_debug.c
+++ b/Linux-PAM/modules/pam_debug/pam_debug.c
@@ -1,7 +1,7 @@
/* pam_permit module */
/*
- * $Id: pam_debug.c,v 1.1.1.1 2002/09/15 20:08:45 hartmans Exp $
+ * $Id: pam_debug.c,v 1.2 2004/09/15 12:06:17 kukuk Exp $
*
* Written by Andrew Morgan <morgan@kernel.org> 2001/02/04
*
@@ -102,7 +102,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
}
if (user == NULL || *user == '\0') {
D(("username not known"));
- pam_set_item(pamh, PAM_USER, (const void *) DEFAULT_USER);
+ retval = pam_set_item(pamh, PAM_USER, (const void *) DEFAULT_USER);
+ if (retval != PAM_SUCCESS)
+ return retval;
}
user = NULL; /* clean up */
diff --git a/Linux-PAM/modules/pam_deny/Makefile b/Linux-PAM/modules/pam_deny/Makefile
index f2a49e1d..2fdd6e11 100644
--- a/Linux-PAM/modules/pam_deny/Makefile
+++ b/Linux-PAM/modules/pam_deny/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:18 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_deny/README b/Linux-PAM/modules/pam_deny/README
index c6b86c79..2eb96d4e 100644
--- a/Linux-PAM/modules/pam_deny/README
+++ b/Linux-PAM/modules/pam_deny/README
@@ -1,4 +1,4 @@
-# $Id: README,v 1.1.1.1 2001/04/29 04:17:18 hartmans Exp $
+# $Id: README,v 1.1.1.1 2000/06/20 22:11:33 agmorgan Exp $
#
this module always fails, it ignores all options.
diff --git a/Linux-PAM/modules/pam_deny/pam_deny.c b/Linux-PAM/modules/pam_deny/pam_deny.c
index d1fa42a3..8be1a8a8 100644
--- a/Linux-PAM/modules/pam_deny/pam_deny.c
+++ b/Linux-PAM/modules/pam_deny/pam_deny.c
@@ -1,7 +1,7 @@
/* pam_permit module */
/*
- * $Id: pam_deny.c,v 1.1.1.1 2001/04/29 04:17:18 hartmans Exp $
+ * $Id: pam_deny.c,v 1.2 2000/12/04 19:02:34 baggins Exp $
*
* Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11
*
diff --git a/Linux-PAM/modules/pam_env/Makefile b/Linux-PAM/modules/pam_env/Makefile
index 25856f04..189f1ee3 100644
--- a/Linux-PAM/modules/pam_env/Makefile
+++ b/Linux-PAM/modules/pam_env/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:18 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_env/README b/Linux-PAM/modules/pam_env/README
index 27d007b9..5053618a 100644
--- a/Linux-PAM/modules/pam_env/README
+++ b/Linux-PAM/modules/pam_env/README
@@ -1,6 +1,6 @@
-# $Date: 2001/04/29 04:17:19 $
-# $Author: hartmans $
-# $Id: README,v 1.1.1.1 2001/04/29 04:17:19 hartmans Exp $
+# $Date: 2000/06/20 22:11:33 $
+# $Author: agmorgan $
+# $Id: README,v 1.1.1.1 2000/06/20 22:11:33 agmorgan Exp $
#
# This is the configuration file for pam_env, a PAM module to load in
# a configurable list of environment variables for a
diff --git a/Linux-PAM/modules/pam_env/pam_env.c b/Linux-PAM/modules/pam_env/pam_env.c
index 2b7533d0..a3cf7684 100644
--- a/Linux-PAM/modules/pam_env/pam_env.c
+++ b/Linux-PAM/modules/pam_env/pam_env.c
@@ -1,7 +1,7 @@
/* pam_mail module */
/*
- * $Id: pam_env.c,v 1.1.1.2 2002/09/15 20:08:46 hartmans Exp $
+ * $Id: pam_env.c,v 1.5 2004/09/15 12:06:17 kukuk Exp $
*
* Written by Dave Kinchlea <kinch@kinch.ark.com> 1997/01/31
* Inspired by Andrew Morgan <morgan@kernel.org>, who also supplied the
@@ -13,7 +13,7 @@
#endif
#define DEFAULT_ETC_ENVFILE "/etc/environment"
-#define DEFAULT_READ_ENVFILE 1
+#define DEFAULT_READ_ENVFILE 0
#include <security/_pam_aconf.h>
@@ -165,8 +165,8 @@ static int _parse_config_file(pam_handle_t *pamh, int ctrl, char **conffile)
return PAM_IGNORE;
}
- /* _pam_assemble_line will provide a complete line from the config file, with all
- * comments removed and any escaped newlines fixed up
+ /* _pam_assemble_line will provide a complete line from the config file,
+ * with all comments removed and any escaped newlines fixed up
*/
while (( retval = _assemble_line(conf, buffer, BUF_SIZE)) > 0) {
@@ -192,12 +192,13 @@ static int _parse_config_file(pam_handle_t *pamh, int ctrl, char **conffile)
(void) fclose(conf);
/* tidy up */
- _clean_var(var); /* We could have got here prematurely, this is safe though */
+ _clean_var(var); /* We could have got here prematurely,
+ * this is safe though */
_pam_overwrite(*conffile);
_pam_drop(*conffile);
file = NULL;
D(("Exit."));
- return (retval<0?PAM_ABORT:PAM_SUCCESS);
+ return (retval != 0 ? PAM_ABORT : PAM_SUCCESS);
}
static int _parse_env_file(pam_handle_t *pamh, int ctrl, char **env_file)
@@ -231,7 +232,7 @@ static int _parse_env_file(pam_handle_t *pamh, int ctrl, char **env_file)
continue;
/* skip over "export " if present so we can be compat with
- bash type declerations */
+ bash type declarations */
if (strncmp(key, "export ", (size_t) 7) == 0)
key += 7;
@@ -279,7 +280,7 @@ static int _parse_env_file(pam_handle_t *pamh, int ctrl, char **env_file)
_pam_drop(*env_file);
file = NULL;
D(("Exit."));
- return (retval<0?PAM_IGNORE:PAM_SUCCESS);
+ return (retval != 0 ? PAM_IGNORE : PAM_SUCCESS);
}
/*
@@ -765,8 +766,8 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
retval = _parse_config_file(pamh, ctrl, &conf_file);
- if(readenv)
- _parse_env_file(pamh, ctrl, &env_file);
+ if(readenv && retval == PAM_SUCCESS)
+ retval = _parse_env_file(pamh, ctrl, &env_file);
/* indicate success or failure */
@@ -798,8 +799,8 @@ int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc
retval = _parse_config_file(pamh, ctrl, &conf_file);
- if(readenv)
- _parse_env_file(pamh, ctrl, &env_file);
+ if(readenv && retval == PAM_SUCCESS)
+ retval = _parse_env_file(pamh, ctrl, &env_file);
/* indicate success or failure */
diff --git a/Linux-PAM/modules/pam_env/pam_env.conf-example b/Linux-PAM/modules/pam_env/pam_env.conf-example
index fa4e0b84..612a31c2 100644
--- a/Linux-PAM/modules/pam_env/pam_env.conf-example
+++ b/Linux-PAM/modules/pam_env/pam_env.conf-example
@@ -1,6 +1,6 @@
-# $Date: 2001/04/29 04:17:19 $
-# $Author: hartmans $
-# $Id: pam_env.conf-example,v 1.1.1.1 2001/04/29 04:17:19 hartmans Exp $
+# $Date: 2004/11/16 14:27:41 $
+# $Author: toady $
+# $Id: pam_env.conf-example,v 1.2 2004/11/16 14:27:41 toady Exp $
#
# This is the configuration file for pam_env, a PAM module to load in
# a configurable list of environment variables for a
@@ -43,6 +43,10 @@
# be used in values using the @{string} syntax. Both the $ and @
# characters can be backslash escaped to be used as literal values
# values can be delimited with "", escaped " not supported.
+# Note that many environment variables that you would like to use
+# may not be set by the time the module is called.
+# For example, HOME is used below several times, but
+# many PAM applications don't make it available by the time you need it.
#
#
# First, some special variables
diff --git a/Linux-PAM/modules/pam_filter/Makefile b/Linux-PAM/modules/pam_filter/Makefile
index caad06c7..e7d7041e 100644
--- a/Linux-PAM/modules/pam_filter/Makefile
+++ b/Linux-PAM/modules/pam_filter/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.2 2002/09/15 20:08:47 hartmans Exp $
+# $Id: Makefile,v 1.4 2001/11/11 07:43:54 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_filter/README b/Linux-PAM/modules/pam_filter/README
index 64bac608..12c4aeb5 100644
--- a/Linux-PAM/modules/pam_filter/README
+++ b/Linux-PAM/modules/pam_filter/README
@@ -1,5 +1,5 @@
#
-# $Id: README,v 1.1.1.1 2001/04/29 04:17:19 hartmans Exp $
+# $Id: README,v 1.1.1.1 2000/06/20 22:11:35 agmorgan Exp $
#
# This describes the behavior of this module with respect to the
# /etc/pam.conf file.
diff --git a/Linux-PAM/modules/pam_filter/include/pam_filter.h b/Linux-PAM/modules/pam_filter/include/pam_filter.h
index f189c911..69e3a3e2 100644
--- a/Linux-PAM/modules/pam_filter/include/pam_filter.h
+++ b/Linux-PAM/modules/pam_filter/include/pam_filter.h
@@ -1,5 +1,5 @@
/*
- * $Id: pam_filter.h,v 1.1.1.1 2001/04/29 04:17:20 hartmans Exp $
+ * $Id: pam_filter.h,v 1.1.1.1 2000/06/20 22:11:36 agmorgan Exp $
*
* this file is associated with the Linux-PAM filter module.
* it was written by Andrew G. Morgan <morgan@linux.kernel.org>
diff --git a/Linux-PAM/modules/pam_filter/pam_filter.c b/Linux-PAM/modules/pam_filter/pam_filter.c
index 0ddd3711..9aa23f29 100644
--- a/Linux-PAM/modules/pam_filter/pam_filter.c
+++ b/Linux-PAM/modules/pam_filter/pam_filter.c
@@ -1,5 +1,5 @@
/*
- * $Id: pam_filter.c,v 1.1.1.2 2002/09/15 20:08:47 hartmans Exp $
+ * $Id: pam_filter.c,v 1.6 2004/11/16 14:27:41 toady Exp $
*
* written by Andrew Morgan <morgan@transmeta.com> with much help from
* Richard Stevens' UNIX Network Programming book.
@@ -21,7 +21,7 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
-#include <termio.h>
+#include <termios.h>
#include <signal.h>
@@ -131,7 +131,7 @@ static int process_args(pam_handle_t *pamh
} else {
char **levp;
const char *tmp;
- int i,size;
+ int i,size, retval;
*filtername = *++argv;
if (ctrl & FILTER_DEBUG) {
@@ -150,7 +150,7 @@ static int process_args(pam_handle_t *pamh
/* the "ARGS" variable */
-#define ARGS_OFFSET 5 /* sizeof('ARGS='); */
+#define ARGS_OFFSET 5 /* strlen('ARGS='); */
#define ARGS_NAME "ARGS="
size += ARGS_OFFSET;
@@ -174,10 +174,18 @@ static int process_args(pam_handle_t *pamh
/* the "SERVICE" variable */
-#define SERVICE_OFFSET 8 /* sizeof('SERVICE='); */
+#define SERVICE_OFFSET 8 /* strlen('SERVICE='); */
#define SERVICE_NAME "SERVICE="
- pam_get_item(pamh, PAM_SERVICE, (const void **)&tmp);
+ retval = pam_get_item(pamh, PAM_SERVICE, (const void **)&tmp);
+ if (retval != PAM_SUCCESS || tmp == NULL) {
+ _pam_log(LOG_CRIT,"service name not found");
+ if (levp) {
+ free(levp[0]);
+ free(levp);
+ }
+ return -1;
+ }
size = SERVICE_OFFSET+strlen(tmp);
levp[1] = (char *) malloc(size+1);
@@ -196,9 +204,10 @@ static int process_args(pam_handle_t *pamh
/* the "USER" variable */
-#define USER_OFFSET 5 /* sizeof('USER='); */
+#define USER_OFFSET 5 /* strlen('USER='); */
#define USER_NAME "USER="
+ tmp = NULL;
pam_get_user(pamh, &tmp, NULL);
if (tmp == NULL) {
tmp = "<unknown>";
@@ -222,7 +231,7 @@ static int process_args(pam_handle_t *pamh
/* the "USER" variable */
-#define TYPE_OFFSET 5 /* sizeof('TYPE='); */
+#define TYPE_OFFSET 5 /* strlen('TYPE='); */
#define TYPE_NAME "TYPE="
size = TYPE_OFFSET+strlen(type);
@@ -278,7 +287,7 @@ static int set_filter(pam_handle_t *pamh, int flags, int ctrl
{
int status=-1;
char terminal[TERMINAL_LEN];
- struct termio stored_mode; /* initial terminal mode settings */
+ struct termios stored_mode; /* initial terminal mode settings */
int fd[2], child=0, child2=0, aterminal;
if (filtername == NULL || *filtername != '/') {
@@ -305,15 +314,15 @@ static int set_filter(pam_handle_t *pamh, int flags, int ctrl
/* set terminal into raw mode.. remember old mode so that we can
revert to it after the child has quit. */
- /* this is termio terminal handling... */
+ /* this is termios terminal handling... */
- if (ioctl(STDIN_FILENO, TCGETA, (char *) &stored_mode ) < 0) {
+ if ( tcgetattr(STDIN_FILENO, &stored_mode) < 0 ) {
/* in trouble, so close down */
close(fd[0]);
_pam_log(LOG_CRIT, "couldn't copy terminal mode");
return PAM_ABORT;
} else {
- struct termio t_mode = stored_mode;
+ struct termios t_mode = stored_mode;
t_mode.c_iflag = 0; /* no input control */
t_mode.c_oflag &= ~OPOST; /* no ouput post processing */
@@ -326,7 +335,7 @@ static int set_filter(pam_handle_t *pamh, int flags, int ctrl
t_mode.c_cc[VMIN] = 1; /* number of chars to satisfy a read */
t_mode.c_cc[VTIME] = 0; /* 0/10th second for chars */
- if (ioctl(STDIN_FILENO, TCSETA, (char *) &t_mode) < 0) {
+ if ( tcsetattr(STDIN_FILENO, TCSAFLUSH, &t_mode) < 0 ) {
close(fd[0]);
_pam_log(LOG_WARNING, "couldn't put terminal in RAW mode");
return PAM_ABORT;
@@ -356,7 +365,7 @@ static int set_filter(pam_handle_t *pamh, int flags, int ctrl
_pam_log(LOG_WARNING,"first fork failed");
if (aterminal) {
- (void) ioctl(STDIN_FILENO, TCSETA, (char *) &stored_mode);
+ (void) tcsetattr(STDIN_FILENO, TCSAFLUSH, &stored_mode);
}
return PAM_AUTH_ERR;
@@ -398,7 +407,7 @@ static int set_filter(pam_handle_t *pamh, int flags, int ctrl
/* initialize the child's terminal to be the way the
parent's was before we set it into RAW mode */
- if (ioctl(fd[1], TCSETA, (char *) &stored_mode) < 0) {
+ if ( tcsetattr(fd[1], TCSANOW, &stored_mode) < 0 ) {
_pam_log(LOG_WARNING,"cannot set slave terminal mode; %s"
,terminal);
close(fd[1]);
@@ -572,7 +581,7 @@ static int set_filter(pam_handle_t *pamh, int flags, int ctrl
if (aterminal) {
/* reset to initial terminal mode */
- (void) ioctl(STDIN_FILENO, TCSETA, (char *) &stored_mode);
+ (void) tcsetattr(STDIN_FILENO, TCSANOW, &stored_mode);
}
if (ctrl & FILTER_DEBUG) {
diff --git a/Linux-PAM/modules/pam_filter/upperLOWER/Makefile b/Linux-PAM/modules/pam_filter/upperLOWER/Makefile
index 3e2d667f..c75f4964 100644
--- a/Linux-PAM/modules/pam_filter/upperLOWER/Makefile
+++ b/Linux-PAM/modules/pam_filter/upperLOWER/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.2 2002/09/15 20:08:47 hartmans Exp $
+# $Id: Makefile,v 1.4 2004/09/22 09:37:47 kukuk Exp $
#
# This directory contains a pam_filter filter executable
#
@@ -12,16 +12,19 @@ TITLE=upperLOWER
#
-CFLAGS += -I../include
+CFLAGS += -I../include -I../../pammodutil/include
OBJS = $(TITLE).o
+LIBS += $(GLIB_LIBS) -L../../pammodutil -lpammodutil
+LDFLAGS = $(LIBS)
+
####################### don't edit below #######################
all: $(TITLE)
$(TITLE): $(OBJS)
- $(CC) $(CFLAGS) -o $(TITLE) $(OBJS)
+ $(CC) $(CFLAGS) -o $(TITLE) $(OBJS) $(LDFLAGS)
$(STRIP) $(TITLE)
install:
diff --git a/Linux-PAM/modules/pam_filter/upperLOWER/upperLOWER.c b/Linux-PAM/modules/pam_filter/upperLOWER/upperLOWER.c
index 59c0e0e3..ee3544a1 100644
--- a/Linux-PAM/modules/pam_filter/upperLOWER/upperLOWER.c
+++ b/Linux-PAM/modules/pam_filter/upperLOWER/upperLOWER.c
@@ -1,5 +1,5 @@
/*
- * $Id: upperLOWER.c,v 1.1.1.2 2002/09/15 20:08:48 hartmans Exp $
+ * $Id: upperLOWER.c,v 1.5 2004/09/22 09:37:48 kukuk Exp $
*
* This is a sample filter program, for use with pam_filter (a module
* provided with Linux-PAM). This filter simply transposes upper and
@@ -21,6 +21,9 @@
#include <unistd.h>
#include <security/pam_filter.h>
+#include <security/pam_modules.h>
+#include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
/* ---------------------------------------------------------------- */
@@ -109,27 +112,27 @@ int main(int argc, char **argv)
/* application errors */
if ( FD_ISSET(APPERR_FILENO,&readers) ) {
- int got = read(APPERR_FILENO, buffer, BUFSIZ);
+ int got = _pammodutil_read(APPERR_FILENO, buffer, BUFSIZ);
if (got <= 0) {
break;
} else {
/* translate to give to real terminal */
if (before_user != NULL)
before_user(buffer, got);
- if ( write(STDERR_FILENO, buffer, got) != got ) {
+ if (_pammodutil_write(STDERR_FILENO, buffer, got) != got ) {
log_this(LOG_WARNING,"couldn't write %d bytes?!",got);
break;
}
}
} else if ( FD_ISSET(APPOUT_FILENO,&readers) ) { /* app output */
- int got = read(APPOUT_FILENO, buffer, BUFSIZ);
+ int got = _pammodutil_read(APPOUT_FILENO, buffer, BUFSIZ);
if (got <= 0) {
break;
} else {
/* translate to give to real terminal */
if (before_user != NULL)
before_user(buffer, got);
- if ( write(STDOUT_FILENO, buffer, got) != got ) {
+ if (_pammodutil_write(STDOUT_FILENO, buffer, got) != got ) {
log_this(LOG_WARNING,"couldn't write %d bytes!?",got);
break;
}
@@ -137,7 +140,7 @@ int main(int argc, char **argv)
}
if ( FD_ISSET(STDIN_FILENO, &readers) ) { /* user input */
- int got = read(STDIN_FILENO, buffer, BUFSIZ);
+ int got = _pammodutil_read(STDIN_FILENO, buffer, BUFSIZ);
if (got < 0) {
log_this(LOG_WARNING,"user input junked");
break;
@@ -145,7 +148,7 @@ int main(int argc, char **argv)
/* translate to give to application */
if (before_app != NULL)
before_app(buffer, got);
- if ( write(APPIN_FILENO, buffer, got) != got ) {
+ if (_pammodutil_write(APPIN_FILENO, buffer, got) != got ) {
log_this(LOG_WARNING,"couldn't pass %d bytes!?",got);
break;
}
diff --git a/Linux-PAM/modules/pam_ftp/Makefile b/Linux-PAM/modules/pam_ftp/Makefile
index a1088e17..456161bf 100644
--- a/Linux-PAM/modules/pam_ftp/Makefile
+++ b/Linux-PAM/modules/pam_ftp/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:21 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:03 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_ftp/pam_ftp.c b/Linux-PAM/modules/pam_ftp/pam_ftp.c
index 1512a65d..64df95ac 100644
--- a/Linux-PAM/modules/pam_ftp/pam_ftp.c
+++ b/Linux-PAM/modules/pam_ftp/pam_ftp.c
@@ -1,7 +1,7 @@
/* pam_ftp module */
/*
- * $Id: pam_ftp.c,v 1.1.1.1 2001/04/29 04:17:21 hartmans Exp $
+ * $Id: pam_ftp.c,v 1.3 2004/09/22 09:37:48 kukuk Exp $
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
*
@@ -58,7 +58,7 @@ static int converse(pam_handle_t *pamh, int nargs
D(("begin to converse\n"));
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
- if ( retval == PAM_SUCCESS ) {
+ if ( retval == PAM_SUCCESS && conv ) {
retval = conv->conv(nargs, ( const struct pam_message ** ) message
, response, conv->appdata_ptr);
@@ -73,6 +73,8 @@ static int converse(pam_handle_t *pamh, int nargs
} else {
_pam_log(LOG_ERR, "couldn't obtain coversation function [%s]"
, pam_strerror(pamh, retval));
+ if (retval == PAM_SUCCESS)
+ retval = PAM_BAD_ITEM; /* conv was NULL */
}
D(("ready to return from module conversation\n"));
diff --git a/Linux-PAM/modules/pam_group/Makefile b/Linux-PAM/modules/pam_group/Makefile
index 11593e25..06c88998 100644
--- a/Linux-PAM/modules/pam_group/Makefile
+++ b/Linux-PAM/modules/pam_group/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:21 hartmans Exp $
+# $Id: Makefile,v 1.3 2003/11/27 07:49:46 kukuk Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
@@ -11,7 +11,7 @@ TITLE=pam_group
LOCAL_CONFILE=./group.conf
INSTALLED_CONFILE=$(SCONFIGD)/group.conf
-DEFS=-DDEFAULT_CONF_FILE=\"$(CONFILE)\"
+DEFS=-DDEFAULT_CONF_FILE=\"$(INSTALLED_CONFILE)\"
CFLAGS += $(DEFS)
MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)"
diff --git a/Linux-PAM/modules/pam_group/pam_group.c b/Linux-PAM/modules/pam_group/pam_group.c
index b6b6ee08..c7b75fe2 100644
--- a/Linux-PAM/modules/pam_group/pam_group.c
+++ b/Linux-PAM/modules/pam_group/pam_group.c
@@ -1,13 +1,13 @@
/* pam_group module */
/*
- * $Id: pam_group.c,v 1.1.1.2 2002/09/15 20:08:48 hartmans Exp $
+ * $Id: pam_group.c,v 1.7 2004/09/24 13:13:20 kukuk Exp $
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/7/6
*/
const static char rcsid[] =
-"$Id: pam_group.c,v 1.1.1.2 2002/09/15 20:08:48 hartmans Exp $;\n"
+"$Id: pam_group.c,v 1.7 2004/09/24 13:13:20 kukuk Exp $;\n"
"Version 0.5 for Linux-PAM\n"
"Copyright (c) Andrew G. Morgan 1996 <morgan@linux.kernel.org>\n";
@@ -57,6 +57,7 @@ typedef enum { AND, OR } operator;
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
/* --- static functions for checking whether the user should be let in --- */
@@ -79,6 +80,12 @@ static void shift_bytes(char *mem, int from, int by)
}
}
+/* This function should initially be called with buf = NULL. If
+ * an error occurs, the file descriptor is closed. Subsequent
+ * calls with a closed descriptor will cause buf to be deallocated.
+ * Therefore, always check buf after calling this to see if an error
+ * occurred.
+ */
static int read_field(int fd, char **buf, int *from, int *to)
{
/* is buf set ? */
@@ -126,6 +133,7 @@ static int read_field(int fd, char **buf, int *from, int *to)
i = read(fd, *to + *buf, PAM_GROUP_BUFLEN - *to);
if (i < 0) {
_log_err("error reading " PAM_GROUP_CONF);
+ close(fd);
return -1;
} else if (!i) {
close(fd);
@@ -165,6 +173,7 @@ static int read_field(int fd, char **buf, int *from, int *to)
} else {
_log_err("internal error in " __FILE__
" at line %d", __LINE__ );
+ close(fd);
return -1;
}
break;
@@ -518,7 +527,7 @@ static int find_member(const char *string, int *at)
#define GROUP_BLK 10
#define blk_size(len) (((len-1 + GROUP_BLK)/GROUP_BLK)*GROUP_BLK)
-static int mkgrplist(char *buf, gid_t **list, int len)
+static int mkgrplist(pam_handle_t *pamh, char *buf, gid_t **list, int len)
{
int l,at=0;
int blks;
@@ -581,7 +590,7 @@ static int mkgrplist(char *buf, gid_t **list, int len)
{
const struct group *grp;
- grp = getgrnam(buf+at);
+ grp = _pammodutil_getgrnam(pamh, buf+at);
if (grp == NULL) {
_log_err("bad group: %s", buf+at);
} else {
@@ -600,8 +609,8 @@ static int mkgrplist(char *buf, gid_t **list, int len)
}
-static int check_account(const char *service, const char *tty
- , const char *user)
+static int check_account(pam_handle_t *pamh, const char *service,
+ const char *tty, const char *user)
{
int from=0,to=0,fd=-1;
char *buffer=NULL;
@@ -700,7 +709,7 @@ static int check_account(const char *service, const char *tty
if (good) {
D(("adding %s to gid list", buffer));
- good = mkgrplist(buffer, &grps, no_grps);
+ good = mkgrplist(pamh, buffer, &grps, no_grps);
if (good < 0) {
no_grps = 0;
} else {
@@ -771,7 +780,7 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
/* only interested in establishing credentials */
setting = flags;
- if (!(setting & PAM_ESTABLISH_CRED)) {
+ if (!(setting & (PAM_ESTABLISH_CRED | PAM_REINITIALIZE_CRED))) {
D(("ignoring call - not for establishing credentials"));
return PAM_SUCCESS; /* don't fail because of this */
}
@@ -823,7 +832,7 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
/* We initialize the pwdb library and check the account */
retval = pwdb_start(); /* initialize */
if (retval == PWDB_SUCCESS) {
- retval = check_account(service,tty,user); /* get groups */
+ retval = check_account(pamh, service,tty,user); /* get groups */
(void) pwdb_end(); /* tidy up */
} else {
D(("failed to initialize pwdb; %s", pwdb_strerror(retval)));
@@ -832,7 +841,7 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags
}
#else /* WANT_PWDB */
- retval = check_account(service,tty,user); /* get groups */
+ retval = check_account(pamh,service,tty,user); /* get groups */
#endif /* WANT_PWDB */
return retval;
diff --git a/Linux-PAM/modules/pam_issue/Makefile b/Linux-PAM/modules/pam_issue/Makefile
index 1bc611af..1bd2be21 100644
--- a/Linux-PAM/modules/pam_issue/Makefile
+++ b/Linux-PAM/modules/pam_issue/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:22 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_issue/pam_issue.c b/Linux-PAM/modules/pam_issue/pam_issue.c
index 1f4853de..5665966e 100644
--- a/Linux-PAM/modules/pam_issue/pam_issue.c
+++ b/Linux-PAM/modules/pam_issue/pam_issue.c
@@ -38,7 +38,7 @@
static int _user_prompt_set = 0;
-char *do_prompt (FILE *);
+static char *do_prompt (FILE *);
/* --- authentication management functions (only) --- */
@@ -84,12 +84,19 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
if ((fd = fopen(issue_file, "r")) != NULL) {
int tot_size = 0;
- if (fstat(fileno(fd), &st) < 0)
+ if (fstat(fileno(fd), &st) < 0) {
+ fclose(fd);
+ if (issue_file)
+ free(issue_file);
return PAM_IGNORE;
+ }
retval = pam_get_item(pamh, PAM_USER_PROMPT,
(const void **) &cur_prompt);
if (retval != PAM_SUCCESS) {
+ fclose(fd);
+ if (issue_file)
+ free(issue_file);
return PAM_IGNORE;
}
if (cur_prompt == NULL) {
@@ -101,6 +108,9 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
if (parse_esc) {
prompt_tmp = do_prompt(fd);
if (prompt_tmp == NULL) {
+ fclose(fd);
+ if (issue_file)
+ free(issue_file);
return PAM_IGNORE;
}
} else {
@@ -108,13 +118,17 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
prompt_tmp = malloc(st.st_size + 1);
if (prompt_tmp == NULL) {
+ fclose(fd);
+ if (issue_file)
+ free(issue_file);
return PAM_IGNORE;
}
memset (prompt_tmp, '\0', st.st_size + 1);
- count = fread(prompt_tmp, sizeof(char *), st.st_size, fd);
+ count = fread(prompt_tmp, 1, st.st_size, fd);
if (count != st.st_size) {
- free(prompt_tmp);
- return PAM_IGNORE;
+ fclose(fd);
+ retval = PAM_IGNORE;
+ goto cleanup;
}
prompt_tmp[st.st_size] = '\0';
}
@@ -130,7 +144,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
{
char *prompt_tmp_tmp = prompt_tmp;
- prompt_tmp = realloc(prompt_tmp, tot_size);
+ prompt_tmp = realloc(prompt_tmp, tot_size + 1);
if (prompt_tmp == NULL) {
prompt_tmp = prompt_tmp_tmp;
retval = PAM_IGNORE;
@@ -151,6 +165,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
} else {
D(("could not open issue_file: %s", issue_file));
+ free(issue_file);
return PAM_IGNORE;
}
@@ -164,14 +179,18 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
return PAM_IGNORE;
}
-char *do_prompt(FILE *fd)
+static char *do_prompt(FILE *fd)
{
int c, size = 1024;
- char *issue = (char *)malloc(size);
+ char *issue;
char buf[1024];
struct utsname uts;
- if (issue == NULL || fd == NULL)
+ if (fd == NULL)
+ return NULL;
+
+ issue = (char *)malloc(size);
+ if (issue == NULL)
return NULL;
issue[0] = '\0'; /* zero this, for strcat to work on first buf */
diff --git a/Linux-PAM/modules/pam_lastlog/Makefile b/Linux-PAM/modules/pam_lastlog/Makefile
index 18042b47..e8062714 100644
--- a/Linux-PAM/modules/pam_lastlog/Makefile
+++ b/Linux-PAM/modules/pam_lastlog/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:22 hartmans Exp $
+# $Id: Makefile,v 1.3 2001/02/10 22:33:10 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_lastlog/pam_lastlog.c b/Linux-PAM/modules/pam_lastlog/pam_lastlog.c
index 89cea3d6..c9c5e24e 100644
--- a/Linux-PAM/modules/pam_lastlog/pam_lastlog.c
+++ b/Linux-PAM/modules/pam_lastlog/pam_lastlog.c
@@ -1,7 +1,7 @@
/* pam_lastlog module */
/*
- * $Id: pam_lastlog.c,v 1.1.1.2 2002/09/15 20:08:49 hartmans Exp $
+ * $Id: pam_lastlog.c,v 1.8 2004/09/24 13:13:20 kukuk Exp $
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
*
@@ -79,6 +79,7 @@ struct lastlog {
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
/* some syslogging */
@@ -149,7 +150,7 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs
D(("begin to converse"));
retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
- if ( retval == PAM_SUCCESS ) {
+ if ( retval == PAM_SUCCESS && conv) {
retval = conv->conv(nargs, ( const struct pam_message ** ) message
, response, conv->appdata_ptr);
@@ -164,6 +165,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs
} else {
_log_err(LOG_ERR, "couldn't obtain coversation function [%s]"
, pam_strerror(pamh, retval));
+ if (retval == PAM_SUCCESS)
+ retval = PAM_BAD_ITEM; /* conv was NULL */
}
D(("ready to return from module conversation"));
@@ -235,8 +238,8 @@ static int last_login_date(pam_handle_t *pamh, int announce, uid_t uid)
sleep(LASTLOG_IGNORE_LOCK_TIME);
}
- win = ( read(last_fd, &last_login, sizeof(last_login))
- == sizeof(last_login) );
+ win = (_pammodutil_read (last_fd, (char *) &last_login,
+ sizeof(last_login)) == sizeof(last_login));
last_lock.l_type = F_UNLCK;
(void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */
@@ -254,10 +257,12 @@ static int last_login_date(pam_handle_t *pamh, int announce, uid_t uid)
if (!(announce & LASTLOG_QUIET)) {
if (last_login.ll_time) {
+ time_t ll_time;
char *the_time;
char *remark;
- the_time = ctime(&last_login.ll_time);
+ ll_time = last_login.ll_time;
+ the_time = ctime(&ll_time);
the_time[-1+strlen(the_time)] = '\0'; /* delete '\n' */
remark = malloc(LASTLOG_MAXSIZE);
@@ -319,13 +324,15 @@ static int last_login_date(pam_handle_t *pamh, int announce, uid_t uid)
/* write latest value */
{
+ time_t ll_time;
const char *remote_host=NULL
, *terminal_line=DEFAULT_TERM;
/* set this login date */
D(("set the most recent login time"));
- (void) time(&last_login.ll_time); /* set the time */
+ (void) time(&ll_time); /* set the time */
+ last_login.ll_time = ll_time;
/* set the remote host */
(void) pam_get_item(pamh, PAM_RHOST, (const void **)&remote_host);
@@ -372,7 +379,8 @@ static int last_login_date(pam_handle_t *pamh, int announce, uid_t uid)
}
D(("writing to the last_log file"));
- (void) write(last_fd, &last_login, sizeof(last_login));
+ _pammodutil_write (last_fd, (char *) &last_login,
+ sizeof (last_login));
last_lock.l_type = F_UNLCK;
(void) fcntl(last_fd, F_SETLK, &last_lock); /* unlock */
@@ -417,7 +425,7 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc
/* what uid? */
- pwd = getpwnam(user);
+ pwd = _pammodutil_getpwnam (pamh, user);
if (pwd == NULL) {
D(("couldn't identify user %s", user));
return PAM_CRED_INSUFFICIENT;
diff --git a/Linux-PAM/modules/pam_limits/Makefile b/Linux-PAM/modules/pam_limits/Makefile
index b7462851..d15fd9f7 100644
--- a/Linux-PAM/modules/pam_limits/Makefile
+++ b/Linux-PAM/modules/pam_limits/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:22 hartmans Exp $
+# $Id: Makefile,v 1.4 2004/09/28 13:48:47 kukuk Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
@@ -21,9 +21,15 @@ CFLAGS += $(DEFS)
MODULE_SIMPLE_INSTALL=bash -f ../install_conf "$(FAKEROOT)" "$(SCONFIGD)" "$(INSTALLED_CONFILE)" "$(TITLE)" "$(LOCAL_CONFILE)"
MODULE_SIMPLE_REMOVE=rm -f $(FAKEROOT)$(INSTALLED_CONFILE)
MODULE_SIMPLE_CLEAN=rm -f ./.ignore_age
+ifeq ($(HAVE_LIBCAP),yes)
+MODULE_SIMPLE_EXTRALIBS=-lcap
+endif
include ../Simple.Rules
+#else
+#include ../dont_makefile
+#endif
else
include ../dont_makefile
diff --git a/Linux-PAM/modules/pam_limits/README b/Linux-PAM/modules/pam_limits/README
index 023b9575..32afb197 100644
--- a/Linux-PAM/modules/pam_limits/README
+++ b/Linux-PAM/modules/pam_limits/README
@@ -39,6 +39,9 @@ Where:
- maxsyslogins - max number of logins on the system
- priority - lower the priority by given value (value can be -ve)
- locks - max locked files (Linux 2.4 and higher)
+ - sigpending - max number of pending signals (Linux 2.6 and higher)
+ - msgqueue - max memory used by POSIX message queues (bytes)
+ (Linux 2.6 and higher)
Note, if you specify a type of '-' but neglect to supply the item and
value fields then the module will never enforce any limits on the
diff --git a/Linux-PAM/modules/pam_limits/limits.skel b/Linux-PAM/modules/pam_limits/limits.skel
index ccb4e103..9ba31b19 100644
--- a/Linux-PAM/modules/pam_limits/limits.skel
+++ b/Linux-PAM/modules/pam_limits/limits.skel
@@ -30,6 +30,8 @@
# - maxlogins - max number of logins for this user
# - priority - the priority to run user process with
# - locks - max number of file locks the user can hold
+# - sigpending - max number of pending signals
+# - msgqueue - max memory used by POSIX message queues (bytes)
#
#<domain> <type> <item> <value>
#
diff --git a/Linux-PAM/modules/pam_limits/pam_limits.c b/Linux-PAM/modules/pam_limits/pam_limits.c
index 6837fdef..1482833a 100644
--- a/Linux-PAM/modules/pam_limits/pam_limits.c
+++ b/Linux-PAM/modules/pam_limits/pam_limits.c
@@ -1,13 +1,13 @@
/*
* pam_limits - impose resource limits when opening a user session
*
- * 1.6 - modified for PLD (added process priority settings)
+ * 1.6 - modified for PLD (added process priority settings)
* by Marcin Korzonek <mkorz@shadow.eu.org>
* 1.5 - Elliot Lee's "max system logins patch"
* 1.4 - addressed bug in configuration file parser
* 1.3 - modified the configuration file format
* 1.2 - added 'debug' and 'conf=' arguments
- * 1.1 - added @group support
+ * 1.1 - added @group support
* 1.0 - initial release - Linux ONLY
*
* See end for Copyright information
@@ -15,7 +15,7 @@
#if !(defined(linux))
#error THIS CODE IS KNOWN TO WORK ONLY ON LINUX !!!
-#endif
+#endif
#include <security/_pam_aconf.h>
@@ -44,17 +44,19 @@
#define LIMITS_DEF_USER 0 /* limit was set by an user entry */
#define LIMITS_DEF_GROUP 1 /* limit was set by a group entry */
-#define LIMITS_DEF_DEFAULT 2 /* limit was set by an default entry */
-#define LIMITS_DEF_NONE 3 /* this limit was not set yet */
-#define LIMITS_DEF_ALL 4 /* limit was set by an default entry */
-#define LIMITS_DEF_ALLGROUP 5 /* limit was set by a group entry */
+#define LIMITS_DEF_ALLGROUP 2 /* limit was set by a group entry */
+#define LIMITS_DEF_ALL 3 /* limit was set by an default entry */
+#define LIMITS_DEF_DEFAULT 4 /* limit was set by an default entry */
+#define LIMITS_DEF_NONE 5 /* this limit was not set yet */
static const char *limits_def_names[] = {
"USER",
"GROUP",
+ "ALLGROUP",
+ "ALL",
"DEFAULT",
"NONE",
- NULL,
+ NULL
};
struct user_limits_struct {
@@ -74,6 +76,7 @@ struct pam_limit_s {
struct user_limits_struct limits[RLIM_NLIMITS];
char conf_file[BUFSIZ];
int utmp_after_pam_call;
+ char login_group[LINE_LENGTH];
};
#define LIMIT_LOGIN RLIM_NLIMITS+1
@@ -88,6 +91,7 @@ struct pam_limit_s {
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
/* logging */
static void _pam_log(int err, const char *format, ...)
@@ -145,62 +149,10 @@ static int _pam_parse(int argc, const char **argv, struct pam_limit_s *pl)
#define LIMIT_ERR 1 /* error setting a limit */
#define LOGIN_ERR 2 /* too many logins err */
-/* checks if a user is on a list of members of the GID 0 group */
-static int is_on_list(char * const *list, const char *member)
-{
- while (*list) {
- if (strcmp(*list, member) == 0)
- return 1;
- list++;
- }
- return 0;
-}
-
-/*
- * Checks if a user is a member of a group - return non-zero if
- * the user is in the group.
- */
-static int is_in_group(const char *user_name, const char *group_name)
-{
- struct passwd *pwd;
- struct group *grp, *pgrp;
- char uname[LINE_LENGTH], gname[LINE_LENGTH];
-
- if (!user_name || !strlen(user_name))
- return 0;
- if (!group_name || !strlen(group_name))
- return 0;
- memset(uname, 0, sizeof(uname));
- strncpy(uname, user_name, sizeof(uname)-1);
- memset(gname, 0, sizeof(gname));
- strncpy(gname, group_name, sizeof(gname)-1);
-
- pwd = getpwnam(uname);
- if (!pwd)
- return 0;
-
- /* the info about this group */
- grp = getgrnam(gname);
- if (!grp)
- return 0;
-
- /* first check: is a member of the group_name group ? */
- if (is_on_list(grp->gr_mem, uname))
- return 1;
-
- /* next check: user primary group is group_name ? */
- pgrp = getgrgid(pwd->pw_gid);
- if (!pgrp)
- return 0;
- if (!strcmp(pgrp->gr_name, gname))
- return 1;
-
- return 0;
-}
-
/* Counts the number of user logins and check against the limit*/
-static int check_logins(const char *name, int limit, int ctrl,
- struct pam_limit_s *pl)
+static int
+check_logins (pam_handle_t *pamh, const char *name, int limit, int ctrl,
+ struct pam_limit_s *pl)
{
struct utmp *ut;
unsigned int count;
@@ -228,7 +180,7 @@ static int check_logins(const char *name, int limit, int ctrl,
standard for this, since if a module wants to actually map a
username then any early utmp entry will be for the unmapped
name = broken.) */
-
+
if (ctrl & PAM_UTMP_EARLY) {
count = 0;
} else {
@@ -252,7 +204,7 @@ static int check_logins(const char *name, int limit, int ctrl,
continue;
}
if ((pl->login_limit_def == LIMITS_DEF_ALLGROUP)
- && !is_in_group(ut->UT_USER, name)) {
+ && !_pammodutil_user_in_group_nam_nam(pamh, ut->UT_USER, pl->login_group)) {
continue;
}
}
@@ -300,7 +252,7 @@ static int init_limits(struct pam_limit_s *pl)
pl->login_limit_def = LIMITS_DEF_NONE;
return retval;
-}
+}
static void process_limit(int source, const char *lim_type,
const char *lim_item, const char *lim_value,
@@ -309,9 +261,9 @@ static void process_limit(int source, const char *lim_type,
int limit_item;
int limit_type = 0;
long limit_value;
- const char **endptr = &lim_value;
+ char *endptr;
const char *value_orig = lim_value;
-
+
if (ctrl & PAM_DEBUG_ARG)
_pam_log(LOG_DEBUG, "%s: processing %s %s %s for %s\n",
__FUNCTION__,lim_type,lim_item,lim_value,
@@ -341,6 +293,14 @@ static void process_limit(int source, const char *lim_type,
else if (strcmp(lim_item, "locks") == 0)
limit_item = RLIMIT_LOCKS;
#endif
+#ifdef RLIMIT_SIGPENDING
+ else if (strcmp(lim_item, "sigpending") == 0)
+ limit_item = RLIMIT_SIGPENDING;
+#endif
+#ifdef RLIMIT_MSGQUEUE
+ else if (strcmp(lim_item, "msgqueue") == 0)
+ limit_item = RLIMIT_MSGQUEUE;
+#endif
else if (strcmp(lim_item, "maxlogins") == 0) {
limit_item = LIMIT_LOGIN;
pl->flag_numsyslogins = 0;
@@ -365,14 +325,10 @@ static void process_limit(int source, const char *lim_type,
return;
}
- /*
- * there is a warning here because the library prototype for this
- * function is incorrect.
- */
- limit_value = strtol(lim_value, endptr, 10);
+ limit_value = strtol (lim_value, &endptr, 10);
/* special case value when limiting logins */
- if (limit_value == 0 && value_orig == *endptr) { /* no chars read */
+ if (limit_value == 0 && value_orig == endptr) { /* no chars read */
if (strcmp(lim_value,"-") != 0) {
_pam_log(LOG_DEBUG,"wrong limit value '%s'", lim_value);
return;
@@ -446,12 +402,12 @@ static void process_limit(int source, const char *lim_type,
return;
}
-static int parse_config_file(const char *uname, int ctrl,
+static int parse_config_file(pam_handle_t *pamh, const char *uname, int ctrl,
struct pam_limit_s *pl)
{
FILE *fil;
char buf[LINE_LENGTH];
-
+
#define CONF_FILE (pl->conf_file[0])?pl->conf_file:LIMITS_FILE
/* check for the LIMITS_FILE */
if (ctrl & PAM_DEBUG_ARG)
@@ -462,7 +418,7 @@ static int parse_config_file(const char *uname, int ctrl,
return PAM_SERVICE_ERR;
}
#undef CONF_FILE
-
+
/* init things */
memset(buf, 0, sizeof(buf));
/* start the show */
@@ -473,14 +429,14 @@ static int parse_config_file(const char *uname, int ctrl,
char value[LINE_LENGTH];
int i,j;
char *tptr;
-
+
tptr = buf;
/* skip the leading white space */
while (*tptr && isspace(*tptr))
tptr++;
strncpy(buf, tptr, sizeof(buf)-1);
buf[sizeof(buf)-1] = '\0';
-
+
/* Rip off the comments */
tptr = strchr(buf,'#');
if (tptr)
@@ -499,7 +455,7 @@ static int parse_config_file(const char *uname, int ctrl,
memset(ltype, 0, sizeof(ltype));
memset(item, 0, sizeof(item));
memset(value, 0, sizeof(value));
-
+
i = sscanf(buf,"%s%s%s%s", domain, ltype, item, value);
D(("scanned line[%d]: domain[%s], ltype[%s], item[%s], value[%s]",
i, domain, ltype, item, value));
@@ -521,7 +477,7 @@ static int parse_config_file(const char *uname, int ctrl,
_pam_log(LOG_DEBUG, "checking if %s is in group %s",
uname, domain + 1);
}
- if (is_in_group(uname, domain+1))
+ if (_pammodutil_user_in_group_nam_nam(pamh, uname, domain+1))
process_limit(LIMITS_DEF_GROUP, ltype, item, value, ctrl,
pl);
} else if (domain[0]=='%') {
@@ -532,9 +488,11 @@ static int parse_config_file(const char *uname, int ctrl,
if (strcmp(domain,"%") == 0)
process_limit(LIMITS_DEF_ALL, ltype, item, value, ctrl,
pl);
- else if (is_in_group(uname, domain+1))
+ else if (_pammodutil_user_in_group_nam_nam(pamh, uname, domain+1)) {
+ strcpy(pl->login_group, domain+1);
process_limit(LIMITS_DEF_ALLGROUP, ltype, item, value, ctrl,
pl);
+ }
} else if (strcmp(domain, "*") == 0)
process_limit(LIMITS_DEF_DEFAULT, ltype, item, value, ctrl,
pl);
@@ -545,7 +503,7 @@ static int parse_config_file(const char *uname, int ctrl,
}
fclose(fil);
return PAM_IGNORE;
- } else if (domain[0] == '@' && is_in_group(uname, domain+1)) {
+ } else if (domain[0] == '@' && _pammodutil_user_in_group_nam_nam(pamh, uname, domain+1)) {
if (ctrl & PAM_DEBUG_ARG) {
_pam_log(LOG_DEBUG, "no limits for '%s' in group '%s'",
uname, domain+1);
@@ -558,10 +516,11 @@ static int parse_config_file(const char *uname, int ctrl,
}
}
fclose(fil);
- return PAM_SUCCESS;
+ return PAM_SUCCESS;
}
-static int setup_limits(const char * uname, uid_t uid, int ctrl,
+static int setup_limits(pam_handle_t *pamh,
+ const char *uname, uid_t uid, int ctrl,
struct pam_limit_s *pl)
{
int i;
@@ -588,7 +547,7 @@ static int setup_limits(const char * uname, uid_t uid, int ctrl,
}
status |= setrlimit(i, &pl->limits[i].limit);
}
-
+
if (status) {
retval = LIMIT_ERR;
}
@@ -601,7 +560,7 @@ static int setup_limits(const char * uname, uid_t uid, int ctrl,
if (uid == 0) {
D(("skip login limit check for uid=0"));
} else if (pl->login_limit > 0) {
- if (check_logins(uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
+ if (check_logins(pamh, uname, pl->login_limit, ctrl, pl) == LOGIN_ERR) {
retval |= LOGIN_ERR;
}
} else if (pl->login_limit == 0) {
@@ -610,7 +569,7 @@ static int setup_limits(const char * uname, uid_t uid, int ctrl,
return retval;
}
-
+
/* now the session stuff */
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
int argc, const char **argv)
@@ -631,7 +590,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
_pam_log(LOG_CRIT, "open_session - error recovering username");
return PAM_SESSION_ERR;
}
-
+
pwd = getpwnam(user_name);
if (!pwd) {
if (ctrl & PAM_DEBUG_ARG)
@@ -639,14 +598,14 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
user_name);
return PAM_SESSION_ERR;
}
-
+
retval = init_limits(&pl);
if (retval != PAM_SUCCESS) {
_pam_log(LOG_WARNING, "cannot initialize");
return PAM_IGNORE;
}
- retval = parse_config_file(pwd->pw_name, ctrl, &pl);
+ retval = parse_config_file(pamh, pwd->pw_name, ctrl, &pl);
if (retval == PAM_IGNORE) {
D(("the configuration file has an applicable '<domain> -' entry"));
return PAM_SUCCESS;
@@ -659,7 +618,7 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags,
if (ctrl & PAM_DO_SETREUID) {
setreuid(pwd->pw_uid, -1);
}
- retval = setup_limits(pwd->pw_name, pwd->pw_uid, ctrl, &pl);
+ retval = setup_limits(pamh, pwd->pw_name, pwd->pw_uid, ctrl, &pl);
if (retval != LIMITED_OK) {
return PAM_PERM_DENIED;
}
@@ -705,13 +664,13 @@ struct pam_module _pam_limits_modstruct = {
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
- *
+ *
* ALTERNATIVELY, this product may be distributed under the terms of
* the GNU Public License, in which case the provisions of the GPL are
* required INSTEAD OF the above restrictions. (This clause is
* necessary due to a potential bad interaction between the GPL and
* the restrictions contained in a BSD-style copyright.)
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
diff --git a/Linux-PAM/modules/pam_listfile/Makefile b/Linux-PAM/modules/pam_listfile/Makefile
index 5a3d6957..c5447c94 100644
--- a/Linux-PAM/modules/pam_listfile/Makefile
+++ b/Linux-PAM/modules/pam_listfile/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:24 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_listfile/pam_listfile.c b/Linux-PAM/modules/pam_listfile/pam_listfile.c
index 934b51fb..965c471d 100644
--- a/Linux-PAM/modules/pam_listfile/pam_listfile.c
+++ b/Linux-PAM/modules/pam_listfile/pam_listfile.c
@@ -1,5 +1,5 @@
/*
- * $Id: pam_listfile.c,v 1.1.1.2 2002/09/15 20:08:51 hartmans Exp $
+ * $Id: pam_listfile.c,v 1.6 2004/09/24 13:13:20 kukuk Exp $
*
*/
@@ -35,9 +35,11 @@
*/
#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
/* some syslogging */
@@ -63,45 +65,6 @@ static int is_on_list(char * const *list, const char *member)
return 0;
}
-/* Checks if a user is a member of a group */
-static int is_on_group(const char *user_name, const char *group_name)
-{
- struct passwd *pwd;
- struct group *grp, *pgrp;
- char uname[BUFSIZ], gname[BUFSIZ];
-
- if (!strlen(user_name))
- return 0;
- if (!strlen(group_name))
- return 0;
- bzero(uname, sizeof(uname));
- strncpy(uname, user_name, sizeof(uname)-1);
- bzero(gname, sizeof(gname));
- strncpy(gname, group_name, sizeof(gname)-1);
-
- pwd = getpwnam(uname);
- if (!pwd)
- return 0;
-
- /* the info about this group */
- grp = getgrnam(gname);
- if (!grp)
- return 0;
-
- /* first check: is a member of the group_name group ? */
- if (is_on_list(grp->gr_mem, uname))
- return 1;
-
- /* next check: user primary group is group_name ? */
- pgrp = getgrgid(pwd->pw_gid);
- if (!pgrp)
- return 0;
- if (!strcmp(pgrp->gr_name, gname))
- return 1;
-
- return 0;
-}
-
/* --- authentication management functions (only) --- */
/* Extended Items that are not directly available via pam_get_item() */
@@ -134,8 +97,6 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar
struct group *grpinfo;
char *itemlist[256]; /* Maximum of 256 items */
- D(("called."));
-
apply_type=APPLY_TYPE_NULL;
memset(apply_val,0,sizeof(apply_val));
@@ -258,7 +219,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar
return PAM_IGNORE;
}
} else if(apply_type==APPLY_TYPE_GROUP) {
- if(!is_on_group(user_name,apply_val)) {
+ if(!_pammodutil_user_in_group_nam_nam(pamh,user_name,apply_val)) {
/* Not a member of apply= group */
#ifdef DEBUG
_pam_log(LOG_DEBUG,
@@ -281,8 +242,14 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar
if (retval != PAM_SUCCESS)
return PAM_SERVICE_ERR;
}
+ if((citem == PAM_TTY) && citemp) {
+ /* Normalize the TTY name. */
+ if(strncmp(citemp, "/dev/", 5) == 0) {
+ citemp += 5;
+ }
+ }
- if(!citemp || (strlen(citemp) <= 0)) {
+ if(!citemp || (strlen(citemp) == 0)) {
/* The item was NULL - we are sure not to match */
return sense?PAM_SUCCESS:PAM_AUTH_ERR;
}
@@ -290,13 +257,13 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar
if(extitem) {
switch(extitem) {
case EI_GROUP:
- userinfo = getpwnam(citemp);
+ userinfo = _pammodutil_getpwnam(pamh, citemp);
if (userinfo == NULL) {
_pam_log(LOG_ERR,LOCAL_LOG_PREFIX "getpwnam(%s) failed",
citemp);
return onerr;
}
- grpinfo = getgrgid(userinfo->pw_gid);
+ grpinfo = _pammodutil_getgrgid(pamh, userinfo->pw_gid);
if (grpinfo == NULL) {
_pam_log(LOG_ERR,LOCAL_LOG_PREFIX "getgrgid(%d) failed",
(int)userinfo->pw_gid);
@@ -317,7 +284,7 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar
/* Assume that we have already gotten PAM_USER in
pam_get_item() - a valid assumption since citem
gets set to PAM_USER in the extitem switch */
- userinfo = getpwnam(citemp);
+ userinfo = _pammodutil_getpwnam(pamh, citemp);
if (userinfo == NULL) {
_pam_log(LOG_ERR,LOCAL_LOG_PREFIX "getpwnam(%s) failed",
citemp);
@@ -371,8 +338,10 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar
assert(PAM_AUTH_ERR != 0);
#endif
if(extitem == EI_GROUP) {
- while((fgets(aline,255,inf) != NULL)
+ while((fgets(aline,sizeof(aline),inf) != NULL)
&& retval) {
+ if(strlen(aline) == 0)
+ continue;
if(aline[strlen(aline) - 1] == '\n')
aline[strlen(aline) - 1] = '\0';
for(i=0;itemlist[i];)
@@ -383,11 +352,21 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **ar
for(i=0;itemlist[i];)
free(itemlist[i++]);
} else {
- while((fgets(aline,255,inf) != NULL)
+ while((fgets(aline,sizeof(aline),inf) != NULL)
&& retval) {
+ char *a = aline;
+ if(strlen(aline) == 0)
+ continue;
if(aline[strlen(aline) - 1] == '\n')
aline[strlen(aline) - 1] = '\0';
- retval = strcmp(aline,citemp);
+ if(strlen(aline) == 0)
+ continue;
+ if(aline[strlen(aline) - 1] == '\r')
+ aline[strlen(aline) - 1] = '\0';
+ if(citem == PAM_TTY)
+ if(strncmp(a, "/dev/", 5) == 0)
+ a += 5;
+ retval = strcmp(a,citemp);
}
}
fclose(inf);
@@ -419,6 +398,13 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
return PAM_SUCCESS;
}
+PAM_EXTERN
+int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ return pam_sm_authenticate(pamh, 0, argc, argv);
+}
+
#ifdef PAM_STATIC
/* static module data */
@@ -427,13 +413,13 @@ struct pam_module _pam_listfile_modstruct = {
"pam_listfile",
pam_sm_authenticate,
pam_sm_setcred,
- NULL,
+ pam_sm_acct_mgmt,
NULL,
NULL,
NULL,
};
-#endif
+#endif /* PAM_STATIC */
/* end of module definition */
diff --git a/Linux-PAM/modules/pam_localuser/Makefile b/Linux-PAM/modules/pam_localuser/Makefile
new file mode 100644
index 00000000..3dc61aa0
--- /dev/null
+++ b/Linux-PAM/modules/pam_localuser/Makefile
@@ -0,0 +1,14 @@
+# $Id: Makefile,v 1.1 2004/09/24 11:49:37 kukuk Exp $
+#
+# This Makefile controls a build process of $(TITLE) module for
+# Linux-PAM. You should not modify this Makefile (unless you know
+# what you are doing!).
+#
+#
+
+include ../../Make.Rules
+
+TITLE=pam_localuser
+MAN8=pam_localuser.8
+
+include ../Simple.Rules
diff --git a/Linux-PAM/modules/pam_localuser/README b/Linux-PAM/modules/pam_localuser/README
new file mode 100644
index 00000000..b8cdf524
--- /dev/null
+++ b/Linux-PAM/modules/pam_localuser/README
@@ -0,0 +1,17 @@
+pam_localuser:
+ Succeeds iff the PAM_USER is listed in /etc/passwd. This seems to be a
+ common policy need (allowing only a subset of network-wide users, and
+ any locally-defined users, to access services). Simpler than using
+ awk to generate a file for use with pam_listfile (-F: '{print $1}'),
+ I guess.
+
+RECOGNIZED ARGUMENTS:
+ debug write debugging messages to syslog
+ file=FILE scan FILE instead of /etc/passwd
+
+MODULE SERVICES PROVIDED:
+ auth,account scan the FILE (/etc/passwd by default) and return
+ a success code if an entry is found for the user
+
+AUTHOR:
+ Nalin Dahyabhai <nalin@redhat.com>
diff --git a/Linux-PAM/modules/pam_localuser/pam_localuser.8 b/Linux-PAM/modules/pam_localuser/pam_localuser.8
new file mode 100644
index 00000000..ce0a9465
--- /dev/null
+++ b/Linux-PAM/modules/pam_localuser/pam_localuser.8
@@ -0,0 +1,36 @@
+.\" Copyright 2000 Red Hat, Inc.
+.TH pam_localuser 8 2000/7/21 "Red Hat" "System Administrator's Manual"
+
+.SH NAME
+pam_localuser \- require users to be listed in /etc/passwd
+
+.SH SYNOPSIS
+.B account sufficient /lib/security/pam_localuser.so \fIargs\fP
+.br
+.B account required /lib/security/pam_wheel.so group=devel
+
+.SH DESCRIPTION
+pam_localuser.so exists to help implement site-wide login policies, where
+they typically include a subset of the network's users and a few accounts
+that are local to a particular workstation. Using pam_localuser.so and
+pam_wheel.so or pam_listfile.so is an effective way to restrict access to
+either local users and/or a subset of the network's users.
+
+This could also be implemented using pam_listfile.so and a very short awk
+script invoked by cron, but it's common enough to have been separated out.
+
+.SH ARGUMENTS
+.IP debug
+turns on debugging
+.IP file=\fBFILE\fP
+uses a file other than \fB/etc/passwd\fP.
+
+.SH FILES
+/etc/passwd
+
+.SH BUGS
+Let's hope not, but if you find any, please report them via the "Bug Track"
+link at http://bugzilla.redhat.com/bugzilla/
+
+.SH AUTHOR
+Nalin Dahyabhai <nalin@redhat.com>
diff --git a/Linux-PAM/modules/pam_localuser/pam_localuser.c b/Linux-PAM/modules/pam_localuser/pam_localuser.c
new file mode 100644
index 00000000..e5496089
--- /dev/null
+++ b/Linux-PAM/modules/pam_localuser/pam_localuser.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2001, 2004 Red Hat, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "../../_pam_aconf.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
+#include "../../libpam/include/security/pam_modules.h"
+#include "../../libpam/include/security/_pam_macros.h"
+
+#define MODULE_NAME "pam_localuser"
+
+PAM_EXTERN
+int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ int i, ret = PAM_SUCCESS;
+ FILE *fp;
+ int debug = 0;
+ const char *filename = "/etc/passwd";
+ char line[LINE_MAX], name[LINE_MAX];
+ const char* user;
+
+ /* process arguments */
+ for(i = 0; i < argc; i++) {
+ if(strcmp("debug", argv[i]) == 0) {
+ debug = 1;
+ }
+ }
+ for(i = 0; i < argc; i++) {
+ if(strncmp("file=", argv[i], 5) == 0) {
+ filename = argv[i] + 5;
+ if(debug) {
+ openlog(MODULE_NAME, LOG_PID, LOG_AUTHPRIV);
+ syslog(LOG_DEBUG, "set filename to \"%s\"",
+ filename);
+ closelog();
+ }
+ }
+ }
+
+ /* open the file */
+ fp = fopen(filename, "r");
+ if(fp == NULL) {
+ openlog(MODULE_NAME, LOG_PID, LOG_AUTHPRIV);
+ syslog(LOG_ERR, "error opening \"%s\": %s", filename,
+ strerror(errno));
+ closelog();
+ return PAM_SYSTEM_ERR;
+ }
+
+ if(pam_get_user(pamh, &user, NULL) != PAM_SUCCESS) {
+ openlog(MODULE_NAME, LOG_PID, LOG_AUTHPRIV);
+ syslog(LOG_ERR, "user name not specified yet");
+ closelog();
+ fclose(fp);
+ return PAM_SYSTEM_ERR;
+ }
+
+ if ((user == NULL) || (strlen(user) == 0)) {
+ openlog(MODULE_NAME, LOG_PID, LOG_AUTHPRIV);
+ syslog(LOG_ERR, "user name not valid");
+ closelog();
+ fclose(fp);
+ return PAM_SYSTEM_ERR;
+ }
+
+ /* scan the file, using fgets() instead of fgetpwent() because i
+ * don't want to mess with applications which call fgetpwent() */
+ ret = PAM_PERM_DENIED;
+ snprintf(name, sizeof(name), "%s:", user);
+ i = strlen(name);
+ while(fgets(line, sizeof(line), fp) != NULL) {
+ if(debug) {
+ openlog(MODULE_NAME, LOG_PID, LOG_AUTHPRIV);
+ syslog(LOG_DEBUG, "checking \"%s\"", line);
+ closelog();
+ }
+ if(strncmp(name, line, i) == 0) {
+ ret = PAM_SUCCESS;
+ break;
+ }
+ }
+
+ /* okay, we're done */
+ fclose(fp);
+ return ret;
+}
+
+PAM_EXTERN
+int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return PAM_SUCCESS;
+}
+
+PAM_EXTERN
+int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
+
+#ifdef PAM_STATIC
+
+/* static module data */
+
+struct pam_module _pam_localuser_modstruct = {
+ "pam_localuser",
+ pam_sm_authenticate,
+ pam_sm_setcred,
+ pam_sm_acct_mgmt,
+ NULL,
+ NULL,
+ NULL,
+};
+
+#endif
diff --git a/Linux-PAM/modules/pam_mail/Makefile b/Linux-PAM/modules/pam_mail/Makefile
index d5e5c44a..2d9b8e9a 100644
--- a/Linux-PAM/modules/pam_mail/Makefile
+++ b/Linux-PAM/modules/pam_mail/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:24 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_mail/pam_mail.c b/Linux-PAM/modules/pam_mail/pam_mail.c
index d63e79b1..7987cb28 100644
--- a/Linux-PAM/modules/pam_mail/pam_mail.c
+++ b/Linux-PAM/modules/pam_mail/pam_mail.c
@@ -1,7 +1,7 @@
/* pam_mail module */
/*
- * $Id: pam_mail.c,v 1.1.1.1 2001/04/29 04:17:24 hartmans Exp $
+ * $Id: pam_mail.c,v 1.6 2004/11/16 14:27:41 toady Exp $
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
* $HOME additions by David Kinchlea <kinch@kinch.ark.com> 1997/1/7
@@ -32,7 +32,7 @@
#define MAIL_ENV_FORMAT MAIL_ENV_NAME "=%s"
#define YOUR_MAIL_VERBOSE_FORMAT "You have %s mail in %s."
#define YOUR_MAIL_STANDARD_FORMAT "You have %smail."
-#define NO_MAIL_STANDARD_FORMAT "No mail."
+#define NO_MAIL_STANDARD_FORMAT "No mail."
/*
* here, we make a definition for the externally accessible function
@@ -46,6 +46,7 @@
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
/* some syslogging */
@@ -142,8 +143,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs
D(("begin to converse"));
- retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
- if ( retval == PAM_SUCCESS ) {
+ retval = pam_get_item( pamh, PAM_CONV, (const void **) &conv ) ;
+ if ( retval == PAM_SUCCESS && conv ) {
retval = conv->conv(nargs, ( const struct pam_message ** ) message
, response, conv->appdata_ptr);
@@ -158,6 +159,8 @@ static int converse(pam_handle_t *pamh, int ctrl, int nargs
} else {
_log_err(LOG_ERR, "couldn't obtain coversation function [%s]"
, pam_strerror(pamh, retval));
+ if (retval == PAM_SUCCESS)
+ retval = PAM_BAD_ITEM; /* conv was NULL */
}
D(("ready to return from module conversation"));
@@ -182,7 +185,7 @@ static int get_folder(pam_handle_t *pamh, int ctrl,
if (ctrl & PAM_NEW_MAIL_DIR) {
path = *path_mail;
if (*path == '~') { /* support for $HOME delivery */
- pwd = getpwnam(user);
+ pwd = _pammodutil_getpwnam(pamh, user);
if (pwd == NULL) {
_log_err(LOG_ERR, "user [%s] unknown", user);
_pam_overwrite(*path_mail);
@@ -234,7 +237,9 @@ static int get_folder(pam_handle_t *pamh, int ctrl,
_pam_overwrite(hash);
_pam_drop(hash);
} else {
- sprintf(folder, "error");
+ _pam_drop(folder);
+ _log_err(LOG_CRIT, "out of memory for mail folder");
+ return PAM_BUF_ERR;
}
}
D(("folder =[%s]", folder));
@@ -386,7 +391,7 @@ PAM_EXTERN
int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
- return _do_mail(pamh,flags,argc,argv,0);;
+ return _do_mail(pamh,flags,argc,argv,0);
}
/* Checking mail as part of the session management */
@@ -467,9 +472,9 @@ static int _do_mail(pam_handle_t *pamh, int flags, int argc,
type = NULL;
}
}
-
- /* Delete environment variable? */
- if (!est)
+
+ /* Delete environment variable? */
+ if ( ! est && ! (ctrl & PAM_NO_ENV) )
(void) pam_putenv(pamh, MAIL_ENV_NAME);
_pam_overwrite(folder); /* clean up */
diff --git a/Linux-PAM/modules/pam_mkhomedir/Makefile b/Linux-PAM/modules/pam_mkhomedir/Makefile
index 14802d55..f017f4a4 100644
--- a/Linux-PAM/modules/pam_mkhomedir/Makefile
+++ b/Linux-PAM/modules/pam_mkhomedir/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:25 hartmans Exp $
+# $Id: Makefile,v 1.3 2000/11/19 23:54:04 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_mkhomedir/README b/Linux-PAM/modules/pam_mkhomedir/README
new file mode 100644
index 00000000..2a3e705e
--- /dev/null
+++ b/Linux-PAM/modules/pam_mkhomedir/README
@@ -0,0 +1,25 @@
+PAM Make Home Dir module
+
+This module will create a users home directory if it does not exist
+when the session begins. This allows users to be present in central
+database (such as nis, kerb or ldap) without using a distributed
+file system or pre-creating a large number of directories.
+
+Here is a sample /etc/pam.d/login file:
+
+ auth requisite pam_securetty.so
+ auth sufficient pam_ldap.so
+ auth required pam_unix.so
+ auth optional pam_group.so
+ auth optional pam_mail.so
+ account requisite pam_time.so
+ account sufficient pam_ldap.so
+ account required pam_unix.so
+ session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
+ session required pam_unix.so
+ session optional pam_lastlog.so
+ password required pam_unix.so
+
+Released under the GNU LGPL version 2 or later
+Originally written by Jason Gunthorpe <jgg@debian.org> Feb 1999
+
diff --git a/Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c b/Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c
index 9a4640dd..f63177bf 100644
--- a/Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c
+++ b/Linux-PAM/modules/pam_mkhomedir/pam_mkhomedir.c
@@ -4,10 +4,10 @@
when the session begins. This allows users to be present in central
database (such as nis, kerb or ldap) without using a distributed
file system or pre-creating a large number of directories.
-
+
Here is a sample /etc/pam.d/login file for Debian GNU/Linux
2.1:
-
+
auth requisite pam_securetty.so
auth sufficient pam_ldap.so
auth required pam_pwdb.so
@@ -19,11 +19,11 @@
session required pam_mkhomedir.so skel=/etc/skel/ umask=0022
session required pam_pwdb.so
session optional pam_lastlog.so
- password required pam_pwdb.so
-
+ password required pam_pwdb.so
+
Released under the GNU LGPL version 2 or later
Originally written by Jason Gunthorpe <jgg@debian.org> Feb 1999
- Structure taken from pam_lastlogin by Andrew Morgan
+ Structure taken from pam_lastlogin by Andrew Morgan
<morgan@parc.power.net> 1996
*/
@@ -51,6 +51,8 @@
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
+
/* argument parsing */
#define MKHOMEDIR_DEBUG 020 /* keep quiet about things */
@@ -98,8 +100,8 @@ static int _pam_parse(int flags, int argc, const char **argv)
return ctrl;
}
-/* This common function is used to send a message to the applications
- conversion function. Our only use is to ask the application to print
+/* This common function is used to send a message to the applications
+ conversion function. Our only use is to ask the application to print
an informative message that we are creating a home directory */
static int converse(pam_handle_t * pamh, int ctrl, int nargs
,struct pam_message **message
@@ -111,7 +113,7 @@ static int converse(pam_handle_t * pamh, int ctrl, int nargs
D(("begin to converse"));
retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv);
- if (retval == PAM_SUCCESS)
+ if (retval == PAM_SUCCESS && conv)
{
retval = conv->conv(nargs, (const struct pam_message **) message
@@ -130,6 +132,8 @@ static int converse(pam_handle_t * pamh, int ctrl, int nargs
{
_log_err(LOG_ERR, "couldn't obtain coversation function [%s]"
,pam_strerror(pamh, retval));
+ if (retval == PAM_SUCCESS)
+ retval = PAM_BAD_ITEM; /* conv was NULL */
}
D(("ready to return from module conversation"));
@@ -187,9 +191,9 @@ static int create_homedir(pam_handle_t * pamh, int ctrl,
/* Create the new directory */
if (mkdir(dest,0700) != 0)
{
- _log_err(LOG_DEBUG, "unable to create directory %s",source);
+ _log_err(LOG_DEBUG, "unable to create directory %s",dest);
return PAM_PERM_DENIED;
- }
+ }
if (chmod(dest,0777 & (~UMask)) != 0 ||
chown(dest,pwd->pw_uid,pwd->pw_gid) != 0)
{
@@ -212,12 +216,19 @@ static int create_homedir(pam_handle_t * pamh, int ctrl,
}
for (Dir = readdir(D); Dir != 0; Dir = readdir(D))
- {
+ {
int SrcFd;
int DestFd;
int Res;
struct stat St;
+#ifndef PATH_MAX
+ char *newsource = NULL, *newdest = NULL;
+ /* track length of buffers */
+ int nslen = 0, ndlen = 0;
+ int slen = strlen(source), dlen = strlen(dest);
+#else
char newsource[PATH_MAX], newdest[PATH_MAX];
+#endif
/* Skip some files.. */
if (strcmp(Dir->d_name,".") == 0 ||
@@ -225,37 +236,124 @@ static int create_homedir(pam_handle_t * pamh, int ctrl,
continue;
/* Determine what kind of file it is. */
+#ifndef PATH_MAX
+ nslen = slen + strlen(Dir->d_name) + 2;
+
+ if (nslen <= 0)
+ return PAM_BUF_ERR;
+
+ if ( (newsource = malloc(nslen)) == NULL )
+ return PAM_BUF_ERR;
+
+ sprintf(newsource, "%s/%s", source, Dir->d_name);
+#else
snprintf(newsource,sizeof(newsource),"%s/%s",source,Dir->d_name);
+#endif
+
if (lstat(newsource,&St) != 0)
+#ifndef PATH_MAX
+ {
+ free(newsource);
+ newsource = NULL;
continue;
+ }
+#else
+ continue;
+#endif
+
/* We'll need the new file's name. */
+#ifndef PATH_MAX
+ ndlen = dlen + strlen(Dir->d_name)+2;
+
+ if (ndlen <= 0)
+ return PAM_BUF_ERR;
+
+ if ( (newdest = malloc(ndlen)) == NULL ) {
+ free(newsource);
+ return PAM_BUF_ERR;
+ }
+
+ sprintf(newdest, "%s/%s", dest, Dir->d_name);
+#else
snprintf(newdest,sizeof(newdest),"%s/%s",dest,Dir->d_name);
+#endif
/* If it's a directory, recurse. */
if (S_ISDIR(St.st_mode))
{
- create_homedir(pamh, ctrl, pwd, newsource, newdest);
+ int retval = create_homedir(pamh, ctrl, pwd, newsource, newdest);
+
+#ifndef PATH_MAX
+ free(newsource); newsource = NULL;
+ free(newdest); newdest = NULL;
+#endif
+
+ if (retval != PAM_SUCCESS) {
+ closedir(D);
+ return retval;
+ }
continue;
}
/* If it's a symlink, create a new link. */
if (S_ISLNK(St.st_mode))
{
+ int pointedlen = 0;
+#ifndef PATH_MAX
+ char *pointed = NULL;
+ {
+ int size = 100;
+
+ while (1) {
+ pointed = (char *) malloc(size);
+ if ( ! pointed ) {
+ free(newsource);
+ free(newdest);
+ return PAM_BUF_ERR;
+ }
+ pointedlen = readlink (newsource, pointed, size);
+ if ( pointedlen < 0 ) break;
+ if ( pointedlen < size ) break;
+ free (pointed);
+ size *= 2;
+ }
+ }
+ if ( pointedlen < 0 )
+ free(pointed);
+ else
+ pointed[pointedlen] = 0;
+#else
char pointed[PATH_MAX];
memset(pointed, 0, sizeof(pointed));
- if(readlink(newsource, pointed, sizeof(pointed) - 1) != -1)
- {
+
+ pointedlen = readlink(newsource, pointed, sizeof(pointed) - 1);
+#endif
+
+ if ( pointedlen >= 0 ) {
if(symlink(pointed, newdest) == 0)
{
if (lchown(newdest,pwd->pw_uid,pwd->pw_gid) != 0)
{
- _log_err(LOG_DEBUG, "unable to chang perms on link %s",
+ closedir(D);
+ _log_err(LOG_DEBUG, "unable to change perms on link %s",
newdest);
+#ifndef PATH_MAX
+ free(pointed);
+ free(newsource);
+ free(newdest);
+#endif
return PAM_PERM_DENIED;
}
}
+#ifndef PATH_MAX
+ free(pointed);
+#endif
}
+#ifndef PATH_MAX
+ free(newsource); newsource = NULL;
+ free(newdest); newdest = NULL;
+#endif
continue;
}
@@ -263,13 +361,24 @@ static int create_homedir(pam_handle_t * pamh, int ctrl,
* the new device node, FIFO, or whatever it is. */
if (!S_ISREG(St.st_mode))
{
+#ifndef PATH_MAX
+ free(newsource); newsource = NULL;
+ free(newdest); newdest = NULL;
+#endif
continue;
}
/* Open the source file */
if ((SrcFd = open(newsource,O_RDONLY)) < 0 || fstat(SrcFd,&St) != 0)
{
+ closedir(D);
_log_err(LOG_DEBUG, "unable to open src file %s",newsource);
+
+#ifndef PATH_MAX
+ free(newsource); newsource = NULL;
+ free(newdest); newdest = NULL;
+#endif
+
return PAM_PERM_DENIED;
}
stat(newsource,&St);
@@ -278,7 +387,13 @@ static int create_homedir(pam_handle_t * pamh, int ctrl,
if ((DestFd = open(newdest,O_WRONLY | O_TRUNC | O_CREAT,0600)) < 0)
{
close(SrcFd);
+ closedir(D);
_log_err(LOG_DEBUG, "unable to open dest file %s",newdest);
+
+#ifndef PATH_MAX
+ free(newsource); newsource = NULL;
+ free(newdest); newdest = NULL;
+#endif
return PAM_PERM_DENIED;
}
@@ -290,26 +405,55 @@ static int create_homedir(pam_handle_t * pamh, int ctrl,
{
close(SrcFd);
close(DestFd);
+ closedir(D);
_log_err(LOG_DEBUG, "unable to chang perms on copy %s",newdest);
+
+#ifndef PATH_MAX
+ free(newsource); newsource = NULL;
+ free(newdest); newdest = NULL;
+#endif
+
return PAM_PERM_DENIED;
}
/* Copy the file */
do
{
- Res = read(SrcFd,remark,sizeof(remark));
- if (Res < 0 || write(DestFd,remark,Res) != Res)
- {
- close(SrcFd);
- close(DestFd);
- _log_err(LOG_DEBUG, "unable to perform IO");
- return PAM_PERM_DENIED;
+ Res = _pammodutil_read(SrcFd,remark,sizeof(remark));
+
+ if (Res == 0)
+ continue;
+
+ if (Res > 0) {
+ if (_pammodutil_write(DestFd,remark,Res) == Res)
+ continue;
}
+
+ /* If we get here, pammodutil_read returned a -1 or
+ _pammodutil_write returned something unexpected. */
+ close(SrcFd);
+ close(DestFd);
+ closedir(D);
+ _log_err(LOG_DEBUG, "unable to perform IO");
+
+#ifndef PATH_MAX
+ free(newsource); newsource = NULL;
+ free(newdest); newdest = NULL;
+#endif
+
+ return PAM_PERM_DENIED;
}
while (Res != 0);
close(SrcFd);
close(DestFd);
+
+#ifndef PATH_MAX
+ free(newsource); newsource = NULL;
+ free(newdest); newdest = NULL;
+#endif
+
}
+ closedir(D);
return PAM_SUCCESS;
}
@@ -324,7 +468,7 @@ int pam_sm_open_session(pam_handle_t * pamh, int flags, int argc
const char *user;
const struct passwd *pwd;
struct stat St;
-
+
/* Parse the flag values */
ctrl = _pam_parse(flags, argc, argv);
@@ -337,7 +481,7 @@ int pam_sm_open_session(pam_handle_t * pamh, int flags, int argc
}
/* Get the password entry */
- pwd = getpwnam(user);
+ pwd = _pammodutil_getpwnam (pamh, user);
if (pwd == NULL)
{
D(("couldn't identify user %s", user));
@@ -353,7 +497,7 @@ int pam_sm_open_session(pam_handle_t * pamh, int flags, int argc
}
/* Ignore */
-PAM_EXTERN
+PAM_EXTERN
int pam_sm_close_session(pam_handle_t * pamh, int flags, int argc
,const char **argv)
{
diff --git a/Linux-PAM/modules/pam_motd/Makefile b/Linux-PAM/modules/pam_motd/Makefile
index ad6a2497..fb83807a 100644
--- a/Linux-PAM/modules/pam_motd/Makefile
+++ b/Linux-PAM/modules/pam_motd/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:26 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_motd/pam_motd.c b/Linux-PAM/modules/pam_motd/pam_motd.c
index 931dfd10..ce695f92 100644
--- a/Linux-PAM/modules/pam_motd/pam_motd.c
+++ b/Linux-PAM/modules/pam_motd/pam_motd.c
@@ -4,7 +4,7 @@
* Modified for pam_motd by Ben Collins <bcollins@debian.org>
*
* Based off of:
- * $Id: pam_motd.c,v 1.1.1.2 2002/09/15 20:08:52 hartmans Exp $
+ * $Id: pam_motd.c,v 1.3 2004/09/22 09:37:49 kukuk Exp $
*
* Written by Michael K. Johnson <johnsonm@redhat.com> 1996/10/24
*
@@ -33,6 +33,7 @@
#define DEFAULT_MOTD "/etc/motd"
#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
/* --- session management functions (only) --- */
@@ -80,24 +81,33 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc,
if ((fd = open(motd_path, O_RDONLY, 0)) >= 0) {
/* fill in message buffer with contents of motd */
- if ((fstat(fd, &st) < 0) || !st.st_size)
+ if ((fstat(fd, &st) < 0) || !st.st_size) {
+ close(fd);
return retval;
+ }
message.msg = mtmp = malloc(st.st_size+1);
/* if malloc failed... */
- if (!message.msg) return retval;
- read(fd, mtmp, st.st_size);
- if (mtmp[st.st_size-1] == '\n')
- mtmp[st.st_size-1] = '\0';
- else
- mtmp[st.st_size] = '\0';
- close(fd);
- /* Use conversation function to give user contents of motd */
- pam_get_item(pamh, PAM_CONV, (const void **)&conversation);
- conversation->conv(1, (const struct pam_message **)&pmessage,
- &resp, conversation->appdata_ptr);
+ if (!message.msg) {
+ close(fd);
+ return retval;
+ }
+ if (_pammodutil_read(fd, mtmp, st.st_size) == st.st_size) {
+ if (mtmp[st.st_size-1] == '\n')
+ mtmp[st.st_size-1] = '\0';
+ else
+ mtmp[st.st_size] = '\0';
+ close(fd);
+
+ /* Use conversation function to give user contents of motd */
+ if (pam_get_item(pamh, PAM_CONV, (const void **)&conversation) ==
+ PAM_SUCCESS && conversation) {
+ conversation->conv(1, (const struct pam_message **)&pmessage,
+ &resp, conversation->appdata_ptr);
+ if (resp)
+ _pam_drop_reply(resp, 1);
+ }
+ }
free(mtmp);
- if (resp)
- _pam_drop_reply(resp, 1);
}
return retval;
diff --git a/Linux-PAM/modules/pam_nologin/Makefile b/Linux-PAM/modules/pam_nologin/Makefile
index 494d2909..2ad38ffd 100644
--- a/Linux-PAM/modules/pam_nologin/Makefile
+++ b/Linux-PAM/modules/pam_nologin/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:26 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_nologin/README b/Linux-PAM/modules/pam_nologin/README
index 5f7d6ced..5de704c3 100644
--- a/Linux-PAM/modules/pam_nologin/README
+++ b/Linux-PAM/modules/pam_nologin/README
@@ -1,4 +1,4 @@
-# $Id: README,v 1.1.1.2 2002/09/15 20:08:52 hartmans Exp $
+# $Id: README,v 1.2 2002/06/27 05:43:28 agmorgan Exp $
#
This module always lets root in; it lets other users in only if the file
diff --git a/Linux-PAM/modules/pam_nologin/pam_nologin.c b/Linux-PAM/modules/pam_nologin/pam_nologin.c
index ea5d86e9..8e7e124a 100644
--- a/Linux-PAM/modules/pam_nologin/pam_nologin.c
+++ b/Linux-PAM/modules/pam_nologin/pam_nologin.c
@@ -1,7 +1,7 @@
/* pam_nologin module */
/*
- * $Id: pam_nologin.c,v 1.1.1.2 2002/09/15 20:08:53 hartmans Exp $
+ * $Id: pam_nologin.c,v 1.6 2005/01/07 15:31:26 t8m Exp $
*
* Written by Michael K. Johnson <johnsonm@redhat.com> 1996/10/24
*
@@ -24,6 +24,7 @@
*/
#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
#include <security/pam_modules.h>
@@ -116,21 +117,29 @@ static int perform_check(pam_handle_t *pamh, struct opt_s *opts)
goto clean_up_fd;
}
- read(fd, mtmp, st.st_size);
- mtmp[st.st_size] = '\000';
+ if (_pammodutil_read(fd, mtmp, st.st_size) == st.st_size) {
+ mtmp[st.st_size] = '\000';
- /*
- * Use conversation function to give user contents of /etc/nologin
- */
+ /*
+ * Use conversation function to give user contents
+ * of /etc/nologin
+ */
- pam_get_item(pamh, PAM_CONV, (const void **)&conversation);
- (void) conversation->conv(1, (const struct pam_message **)&pmessage,
- &resp, conversation->appdata_ptr);
- free(mtmp);
+ if (pam_get_item(pamh, PAM_CONV, (const void **)&conversation)
+ == PAM_SUCCESS && conversation && conversation->conv) {
+ (void) conversation->conv(1,
+ (const struct pam_message **)&pmessage,
+ &resp, conversation->appdata_ptr);
- if (resp) {
- _pam_drop_reply(resp, 1);
+ if (resp) {
+ _pam_drop_reply(resp, 1);
+ }
+ }
}
+ else
+ retval = PAM_SYSTEM_ERR;
+
+ free(mtmp);
clean_up_fd:
@@ -192,6 +201,6 @@ struct pam_module _pam_nologin_modstruct = {
NULL,
};
-#endif
+#endif /* PAM_STATIC */
/* end of module definition */
diff --git a/Linux-PAM/modules/pam_permit/Makefile b/Linux-PAM/modules/pam_permit/Makefile
index 23835be4..49f3b3dd 100644
--- a/Linux-PAM/modules/pam_permit/Makefile
+++ b/Linux-PAM/modules/pam_permit/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:26 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:04 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_permit/README b/Linux-PAM/modules/pam_permit/README
index 15d95942..52e7364e 100644
--- a/Linux-PAM/modules/pam_permit/README
+++ b/Linux-PAM/modules/pam_permit/README
@@ -1,4 +1,4 @@
-# $Id: README,v 1.1.1.1 2001/04/29 04:17:26 hartmans Exp $
+# $Id: README,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $
#
this module always returns PAM_SUCCESS, it ignores all options.
diff --git a/Linux-PAM/modules/pam_permit/pam_permit.c b/Linux-PAM/modules/pam_permit/pam_permit.c
index 1041ca84..08d464b8 100644
--- a/Linux-PAM/modules/pam_permit/pam_permit.c
+++ b/Linux-PAM/modules/pam_permit/pam_permit.c
@@ -1,7 +1,7 @@
/* pam_permit module */
/*
- * $Id: pam_permit.c,v 1.1.1.1 2001/04/29 04:17:26 hartmans Exp $
+ * $Id: pam_permit.c,v 1.3 2004/09/22 09:37:49 kukuk Exp $
*
* Written by Andrew Morgan <morgan@parc.power.net> 1996/3/11
*
@@ -45,7 +45,9 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
}
if (user == NULL || *user == '\0') {
D(("username not known"));
- pam_set_item(pamh, PAM_USER, (const void *) DEFAULT_USER);
+ retval = pam_set_item(pamh, PAM_USER, (const void *) DEFAULT_USER);
+ if (retval != PAM_SUCCESS)
+ return PAM_USER_UNKNOWN;
}
user = NULL; /* clean up */
diff --git a/Linux-PAM/modules/pam_pwdb/BUGS b/Linux-PAM/modules/pam_pwdb/BUGS
index 7258822c..d51686e5 100644
--- a/Linux-PAM/modules/pam_pwdb/BUGS
+++ b/Linux-PAM/modules/pam_pwdb/BUGS
@@ -1,3 +1,3 @@
-$Id: BUGS,v 1.1.1.1 2001/04/29 04:17:27 hartmans Exp $
+$Id: BUGS,v 1.2 2000/12/04 19:02:34 baggins Exp $
As of Linux-PAM-0.52 this is new. No known bugs yet.
diff --git a/Linux-PAM/modules/pam_pwdb/CHANGELOG b/Linux-PAM/modules/pam_pwdb/CHANGELOG
index 78c1a239..a3614031 100644
--- a/Linux-PAM/modules/pam_pwdb/CHANGELOG
+++ b/Linux-PAM/modules/pam_pwdb/CHANGELOG
@@ -1,4 +1,4 @@
-$Id: CHANGELOG,v 1.1.1.1 2001/04/29 04:17:27 hartmans Exp $
+$Id: CHANGELOG,v 1.1.1.1 2000/06/20 22:11:46 agmorgan Exp $
Tue Apr 23 12:28:09 EDT 1996 (Alexander O. Yuriev alex@bach.cis.temple.edu)
diff --git a/Linux-PAM/modules/pam_pwdb/Makefile b/Linux-PAM/modules/pam_pwdb/Makefile
index bce2950f..228c6704 100644
--- a/Linux-PAM/modules/pam_pwdb/Makefile
+++ b/Linux-PAM/modules/pam_pwdb/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:27 hartmans Exp $
+# $Id: Makefile,v 1.3 2004/09/28 13:48:47 kukuk Exp $
#
# This Makefile controls a build process of the pam_unix module
# for Linux-PAM. You should not modify this Makefile.
@@ -17,6 +17,9 @@ EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\"
ifeq ($(HAVE_LIBCRYPT),yes)
EXTRALS += -lcrypt
endif
+ifeq ($(HAVE_LIBNSL),yes)
+ EXTRALS += -lnsl
+endif
TITLE=pam_pwdb
CHKPWD=pwdb_chkpwd
@@ -53,7 +56,7 @@ info:
$(CHKPWD): pwdb_chkpwd.o md5_good.o md5_broken.o \
md5_crypt_good.o md5_crypt_broken.o
- $(CC) -o $(CHKPWD) $^ -lpwdb
+ $(CC) $(CFLAGS) -o $(CHKPWD) $^ $(LDFLAGS) -lpwdb $(EXTRALS)
pwdb_chkpwd.o: pwdb_chkpwd.c pam_unix_md.-c bigcrypt.-c
diff --git a/Linux-PAM/modules/pam_pwdb/TODO b/Linux-PAM/modules/pam_pwdb/TODO
index 04635859..520a262e 100644
--- a/Linux-PAM/modules/pam_pwdb/TODO
+++ b/Linux-PAM/modules/pam_pwdb/TODO
@@ -1,4 +1,4 @@
-$Id: TODO,v 1.1.1.1 2001/04/29 04:17:27 hartmans Exp $
+$Id: TODO,v 1.1.1.1 2000/06/20 22:11:47 agmorgan Exp $
* get NIS working
* .. including "nonis" argument
diff --git a/Linux-PAM/modules/pam_pwdb/md5.c b/Linux-PAM/modules/pam_pwdb/md5.c
index a0e5a974..44282941 100644
--- a/Linux-PAM/modules/pam_pwdb/md5.c
+++ b/Linux-PAM/modules/pam_pwdb/md5.c
@@ -1,4 +1,4 @@
-/* $Id: md5.c,v 1.1.1.1 2001/04/29 04:17:27 hartmans Exp $
+/* $Id: md5.c,v 1.2 2000/12/04 19:02:34 baggins Exp $
*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
diff --git a/Linux-PAM/modules/pam_pwdb/md5_crypt.c b/Linux-PAM/modules/pam_pwdb/md5_crypt.c
index 28f22727..826087f2 100644
--- a/Linux-PAM/modules/pam_pwdb/md5_crypt.c
+++ b/Linux-PAM/modules/pam_pwdb/md5_crypt.c
@@ -1,4 +1,4 @@
-/* $Id: md5_crypt.c,v 1.1.1.1 2001/04/29 04:17:27 hartmans Exp $
+/* $Id: md5_crypt.c,v 1.2 2000/12/04 19:02:34 baggins Exp $
*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
diff --git a/Linux-PAM/modules/pam_pwdb/pam_pwdb.c b/Linux-PAM/modules/pam_pwdb/pam_pwdb.c
index c2a5639c..8c75ac23 100644
--- a/Linux-PAM/modules/pam_pwdb/pam_pwdb.c
+++ b/Linux-PAM/modules/pam_pwdb/pam_pwdb.c
@@ -1,5 +1,5 @@
/*
- * $Id: pam_pwdb.c,v 1.1.1.1 2001/04/29 04:17:28 hartmans Exp $
+ * $Id: pam_pwdb.c,v 1.3 2000/11/19 23:54:04 agmorgan Exp $
*
* This is the single file that will be compiled for pam_unix.
* it includes each of the modules that have beed defined in the .-c
@@ -14,7 +14,7 @@
*/
static const char rcsid[] =
-"$Id: pam_pwdb.c,v 1.1.1.1 2001/04/29 04:17:28 hartmans Exp $\n"
+"$Id: pam_pwdb.c,v 1.3 2000/11/19 23:54:04 agmorgan Exp $\n"
" - PWDB Pluggable Authentication module. <morgan@linux.kernel.org>"
;
diff --git a/Linux-PAM/modules/pam_pwdb/pam_unix_acct.-c b/Linux-PAM/modules/pam_pwdb/pam_unix_acct.-c
index 3a6ff1ed..adcb6538 100644
--- a/Linux-PAM/modules/pam_pwdb/pam_unix_acct.-c
+++ b/Linux-PAM/modules/pam_pwdb/pam_unix_acct.-c
@@ -1,11 +1,11 @@
/*
- * $Id: pam_unix_acct.-c,v 1.1.1.1 2001/04/29 04:17:28 hartmans Exp $
+ * $Id: pam_unix_acct.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $
*
* See end of file for copyright information
*/
static const char rcsid_acct[] =
-"$Id: pam_unix_acct.-c,v 1.1.1.1 2001/04/29 04:17:28 hartmans Exp $\n"
+"$Id: pam_unix_acct.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $\n"
" - PAM_PWDB account management <gafton@redhat.com>";
/* the shadow suite has accout managment.. */
diff --git a/Linux-PAM/modules/pam_pwdb/pam_unix_auth.-c b/Linux-PAM/modules/pam_pwdb/pam_unix_auth.-c
index 14d74b74..31230394 100644
--- a/Linux-PAM/modules/pam_pwdb/pam_unix_auth.-c
+++ b/Linux-PAM/modules/pam_pwdb/pam_unix_auth.-c
@@ -1,11 +1,11 @@
/*
- * $Id: pam_unix_auth.-c,v 1.1.1.1 2001/04/29 04:17:28 hartmans Exp $
+ * $Id: pam_unix_auth.-c,v 1.1.1.1 2000/06/20 22:11:49 agmorgan Exp $
*
* See end of file for Copyright information.
*/
static const char rcsid_auth[] =
-"$Id: pam_unix_auth.-c,v 1.1.1.1 2001/04/29 04:17:28 hartmans Exp $: pam_unix_auth.-c,v 1.2 1996/09/05 06:46:53 morgan Exp morgan $\n"
+"$Id: pam_unix_auth.-c,v 1.1.1.1 2000/06/20 22:11:49 agmorgan Exp $: pam_unix_auth.-c,v 1.2 1996/09/05 06:46:53 morgan Exp morgan $\n"
" - PAM_PWDB authentication functions. <morgan@parc.power.net>";
/*
diff --git a/Linux-PAM/modules/pam_pwdb/pam_unix_passwd.-c b/Linux-PAM/modules/pam_pwdb/pam_unix_passwd.-c
index dc106431..7ed65000 100644
--- a/Linux-PAM/modules/pam_pwdb/pam_unix_passwd.-c
+++ b/Linux-PAM/modules/pam_pwdb/pam_unix_passwd.-c
@@ -1,7 +1,7 @@
-/* $Id: pam_unix_passwd.-c,v 1.1.1.2 2002/09/15 20:08:55 hartmans Exp $ */
+/* $Id: pam_unix_passwd.-c,v 1.3 2001/11/12 06:57:38 agmorgan Exp $ */
static const char rcsid_pass[] =
-"$Id: pam_unix_passwd.-c,v 1.1.1.2 2002/09/15 20:08:55 hartmans Exp $\n"
+"$Id: pam_unix_passwd.-c,v 1.3 2001/11/12 06:57:38 agmorgan Exp $\n"
" - PAM_PWDB password module <morgan@parc.power.net>"
;
diff --git a/Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c b/Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c
index adb286e2..a1fc65ff 100644
--- a/Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c
+++ b/Linux-PAM/modules/pam_pwdb/pam_unix_pwupd.-c
@@ -1,5 +1,5 @@
/*
- * $Id: pam_unix_pwupd.-c,v 1.1.1.1 2001/04/29 04:17:29 hartmans Exp $
+ * $Id: pam_unix_pwupd.-c,v 1.1.1.1 2000/06/20 22:11:51 agmorgan Exp $
*
* This file contains the routines to update the passwd databases.
*/
diff --git a/Linux-PAM/modules/pam_pwdb/pam_unix_sess.-c b/Linux-PAM/modules/pam_pwdb/pam_unix_sess.-c
index 3e03fc55..395bd9bb 100644
--- a/Linux-PAM/modules/pam_pwdb/pam_unix_sess.-c
+++ b/Linux-PAM/modules/pam_pwdb/pam_unix_sess.-c
@@ -1,11 +1,11 @@
/*
- * $Id: pam_unix_sess.-c,v 1.1.1.1 2001/04/29 04:17:29 hartmans Exp $
+ * $Id: pam_unix_sess.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $
*
* See end for Copyright information
*/
static const char rcsid_sess[] =
-"$Id: pam_unix_sess.-c,v 1.1.1.1 2001/04/29 04:17:29 hartmans Exp $\n"
+"$Id: pam_unix_sess.-c,v 1.2 2000/12/04 19:02:34 baggins Exp $\n"
" - PAM_PWDB session management. morgan@parc.power.net";
/* Define internal functions */
diff --git a/Linux-PAM/modules/pam_pwdb/pwdb_chkpwd.c b/Linux-PAM/modules/pam_pwdb/pwdb_chkpwd.c
index 0b55c952..36c248ef 100644
--- a/Linux-PAM/modules/pam_pwdb/pwdb_chkpwd.c
+++ b/Linux-PAM/modules/pam_pwdb/pwdb_chkpwd.c
@@ -1,5 +1,5 @@
/*
- * $Id: pwdb_chkpwd.c,v 1.1.1.2 2002/09/15 20:08:55 hartmans Exp $
+ * $Id: pwdb_chkpwd.c,v 1.4 2001/12/09 21:44:58 agmorgan Exp $
*
* This program is designed to run setuid(root) or with sufficient
* privilege to read all of the unix password databases. It is designed
diff --git a/Linux-PAM/modules/pam_pwdb/support.-c b/Linux-PAM/modules/pam_pwdb/support.-c
index 623fe2c3..bfa4e8a1 100644
--- a/Linux-PAM/modules/pam_pwdb/support.-c
+++ b/Linux-PAM/modules/pam_pwdb/support.-c
@@ -1,5 +1,5 @@
/*
- * $Id: support.-c,v 1.1.1.2 2002/09/15 20:08:55 hartmans Exp $
+ * $Id: support.-c,v 1.6 2004/09/15 12:06:17 kukuk Exp $
*
* Copyright information at end of file.
*/
@@ -79,8 +79,9 @@ typedef struct {
#define UNIX_UNIX 19 /* wish to use /etc/passwd for pwd */
#define UNIX_BIGCRYPT 20 /* use DEC-C2 crypt()^x function */
#define UNIX_LIKE_AUTH 21 /* need to auth for setcred to work */
+#define UNIX_NOREAP 22 /* don't reap child process */
/* -------------- */
-#define UNIX_CTRLS_ 22 /* number of ctrl arguments defined */
+#define UNIX_CTRLS_ 23 /* number of ctrl arguments defined */
static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = {
@@ -109,6 +110,7 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] = {
/* UNIX_UNIX */ { "unix", _ALL_ON_^(050000), 01000000 },
/* UNIX_BIGCRYPT */ { "bigcrypt", _ALL_ON_^(020000), 02000000 },
/* UNIX_LIKE_AUTH */ { "likeauth", _ALL_ON_, 04000000 },
+/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 010000000 },
};
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
@@ -342,13 +344,15 @@ static void _cleanup_failures(pam_handle_t *pamh, void *fl, int err)
* verify the password of a user
*/
+#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd,
- const char *user)
+ unsigned int ctrl, const char *user)
{
int retval, child, fds[2];
+ void (*sighandler)(int) = NULL;
D(("called."));
/* create a pipe for the password */
@@ -357,6 +361,18 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd,
return PAM_AUTH_ERR;
}
+ if (off(UNIX_NOREAP, ctrl)) {
+ /*
+ * This code arranges that the demise of the child does not cause
+ * the application to receive a signal it is not expecting - which
+ * may kill the application or worse.
+ *
+ * The "noreap" module argument is provided so that the admin can
+ * override this behavior.
+ */
+ sighandler = signal(SIGCHLD, SIG_DFL);
+ }
+
/* fork */
child = fork();
if (child == 0) {
@@ -397,6 +413,10 @@ static int pwdb_run_helper_binary(pam_handle_t *pamh, const char *passwd,
retval = PAM_AUTH_ERR;
}
+ if (sighandler != NULL) {
+ (void) signal(SIGCHLD, sighandler); /* restore old signal handler */
+ }
+
D(("returning %d", retval));
return retval;
}
@@ -468,7 +488,7 @@ static int _unix_verify_password(pam_handle_t *pamh, const char *name,
if (geteuid()) {
/* we are not root perhaps this is the reason? Run helper */
D(("running helper binary"));
- retval = pwdb_run_helper_binary(pamh, p, name);
+ retval = pwdb_run_helper_binary(pamh, p, ctrl, name);
} else {
retval = PAM_AUTHINFO_UNAVAIL;
_log_err(LOG_ALERT, "get passwd; %s", pwdb_strerror(retval));
diff --git a/Linux-PAM/modules/pam_radius/pam_radius.h b/Linux-PAM/modules/pam_radius/pam_radius.h
index 8193c844..67230243 100644
--- a/Linux-PAM/modules/pam_radius/pam_radius.h
+++ b/Linux-PAM/modules/pam_radius/pam_radius.h
@@ -1,5 +1,5 @@
/*
- * $Id: pam_radius.h,v 1.1.1.1 2001/04/29 04:17:32 hartmans Exp $
+ * $Id: pam_radius.h,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
*/
#ifndef PAM_RADIUS_H
diff --git a/Linux-PAM/modules/pam_rhosts/Makefile b/Linux-PAM/modules/pam_rhosts/Makefile
index 0c4ec77e..d12e00c0 100644
--- a/Linux-PAM/modules/pam_rhosts/Makefile
+++ b/Linux-PAM/modules/pam_rhosts/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:32 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_rhosts/pam_rhosts_auth.c b/Linux-PAM/modules/pam_rhosts/pam_rhosts_auth.c
index 7266b4e8..979580ec 100644
--- a/Linux-PAM/modules/pam_rhosts/pam_rhosts_auth.c
+++ b/Linux-PAM/modules/pam_rhosts/pam_rhosts_auth.c
@@ -42,7 +42,7 @@
#define USER_RHOSTS_FILE "/.rhosts" /* prefixed by user's home dir */
-#ifdef linux
+#ifdef __linux__
#include <endian.h>
#endif
@@ -50,6 +50,10 @@
#include <sys/fsuid.h>
#endif /* HAVE_SYS_FSUID_H */
+#ifdef HAVE_NET_IF_H
+#include <sys/if.h>
+#endif
+
#include <sys/types.h>
#include <sys/uio.h>
#include <string.h>
@@ -74,19 +78,13 @@ int innetgr(const char *, const char *, const char *,const char *);
#include <ctype.h>
#include <net/if.h>
-#ifdef linux
-# include <linux/sockios.h>
-# ifndef __USE_MISC
-# define __USE_MISC
-# include <sys/fsuid.h>
-# endif /* __USE_MISC */
-#endif
#include <pwd.h>
#include <grp.h>
#include <sys/file.h>
#include <sys/signal.h>
#include <sys/stat.h>
+#include <stdint.h>
#include <syslog.h>
#ifndef _PATH_HEQUIV
#define _PATH_HEQUIV "/etc/hosts.equiv"
@@ -98,8 +96,17 @@ int innetgr(const char *, const char *, const char *,const char *);
#include <security/_pam_macros.h>
#include <security/_pam_modutil.h>
-/* to the best of my knowledge, all modern UNIX boxes have 32 bit integers */
+#ifdef _ISOC9X_SOURCE
+#include <inttypes.h>
+#define U32 uint32_t
+#else
+/* to the best of my knowledge, all modern UNIX boxes have 32 bits integers */
#define U32 unsigned int
+#endif /* _ISOC9X_SOURCE */
+
+/* Use the C99 type; older platforms will need this to be typedef'ed
+ elsewhere */
+#define U32 uint32_t
/*
@@ -183,7 +190,7 @@ static void set_option (struct _options *opts, const char *arg)
return;
}
- if (strcmp(arg, "superuser=") == 0) {
+ if (strncmp(arg, "superuser=", sizeof("superuser=")-1) == 0) {
opts->superuser = arg+sizeof("superuser=")-1;
return;
}
@@ -298,7 +305,7 @@ __icheckhost (pam_handle_t *pamh, struct _options *opts, U32 raddr
hp = gethostbyname(lhost);
if (hp == NULL)
return (0);
-
+
/* Spin through ip addresses. */
for (pp = hp->h_addr_list; *pp; ++pp)
if (!memcmp (&raddr, *pp, sizeof (U32)))
@@ -413,7 +420,7 @@ __ivaliduser (pam_handle_t *pamh, struct _options *opts,
user = p; /* this is the user's name */
while (*p && !isspace(*p))
++p; /* find end of user's name */
- } else
+ } else
user = p;
*p = '\0'; /* <nul> terminate username (+host?) */
@@ -485,7 +492,7 @@ pam_iruserok(pam_handle_t *pamh,
No hosts.equiv file on system.
} */
}
-
+
if ( opts->opt_no_rhosts )
return 1;
@@ -495,10 +502,10 @@ pam_iruserok(pam_handle_t *pamh,
pwd = _pammodutil_getpwnam(pamh, luser);
if (pwd == NULL) {
- /*
+ /*
* luser is assumed to be valid because of an earlier check for uid = 0
* we don't log this error twice. However, this shouldn't happen !
- * --cristiang
+ * --cristiang
*/
return(1);
}
@@ -520,7 +527,7 @@ pam_iruserok(pam_handle_t *pamh,
*/
/* We are root, this will not fail */
-#ifdef linux
+#ifdef __linux__
/* If we are on linux the better way is setfsuid */
uid = setfsuid(pwd->pw_uid);
hostf = fopen(pbuf, "r");
@@ -555,7 +562,7 @@ pam_iruserok(pam_handle_t *pamh,
/* private group caveat */
if (opts->opt_private_group) {
- struct group *grp = getgrgid(sbuf.st_gid);
+ struct group *grp = _pammodutil_getgrgid(pamh, sbuf.st_gid);
if (NULL == grp || NULL == grp->gr_name
|| strcmp(luser,grp->gr_name)) {
@@ -596,7 +603,7 @@ exit_function:
* they are reset before we exit.
*/
-#ifdef linux
+#ifdef __linux__
setfsuid(uid);
#else
(void)seteuid(uid);
@@ -657,9 +664,9 @@ pam_ruserok (pam_handle_t *pamh,
*/
static int _pam_auth_rhosts (pam_handle_t *pamh,
- int flags,
+ int flags,
int argc,
- const char **argv)
+ const char **argv)
{
int retval;
const char *luser = NULL;
@@ -750,9 +757,9 @@ static int _pam_auth_rhosts (pam_handle_t *pamh,
/* --- authentication management functions --- */
PAM_EXTERN
-int pam_sm_authenticate (pam_handle_t *pamh,
+int pam_sm_authenticate (pam_handle_t *pamh,
int flags,
- int argc,
+ int argc,
const char **argv)
{
int retval;
diff --git a/Linux-PAM/modules/pam_rootok/Makefile b/Linux-PAM/modules/pam_rootok/Makefile
index f6c58635..b908b115 100644
--- a/Linux-PAM/modules/pam_rootok/Makefile
+++ b/Linux-PAM/modules/pam_rootok/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:33 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_rootok/README b/Linux-PAM/modules/pam_rootok/README
index 4e19c097..43b92e6c 100644
--- a/Linux-PAM/modules/pam_rootok/README
+++ b/Linux-PAM/modules/pam_rootok/README
@@ -1,4 +1,4 @@
-# $Id: README,v 1.1.1.2 2002/09/15 20:08:57 hartmans Exp $
+# $Id: README,v 1.2 2001/11/27 05:37:30 agmorgan Exp $
#
this module is an authentication module that performs one task: if the
diff --git a/Linux-PAM/modules/pam_rootok/pam_rootok.c b/Linux-PAM/modules/pam_rootok/pam_rootok.c
index 57ddebe5..e1e09b6e 100644
--- a/Linux-PAM/modules/pam_rootok/pam_rootok.c
+++ b/Linux-PAM/modules/pam_rootok/pam_rootok.c
@@ -1,7 +1,7 @@
/* pam_rootok module */
/*
- * $Id: pam_rootok.c,v 1.1.1.2 2002/09/15 20:08:57 hartmans Exp $
+ * $Id: pam_rootok.c,v 1.3 2002/05/26 23:00:28 agmorgan Exp $
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
*/
diff --git a/Linux-PAM/modules/pam_securetty/Makefile b/Linux-PAM/modules/pam_securetty/Makefile
index 65e50d51..8ac853c5 100644
--- a/Linux-PAM/modules/pam_securetty/Makefile
+++ b/Linux-PAM/modules/pam_securetty/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:33 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_securetty/pam_securetty.c b/Linux-PAM/modules/pam_securetty/pam_securetty.c
index 9e6121e8..3a9ae421 100644
--- a/Linux-PAM/modules/pam_securetty/pam_securetty.c
+++ b/Linux-PAM/modules/pam_securetty/pam_securetty.c
@@ -21,8 +21,7 @@
#include <stdarg.h>
#include <pwd.h>
#include <string.h>
-
-#define PAM_SM_AUTH
+#include <ctype.h>
/*
* here, we make a definition for the externally accessible function
@@ -32,8 +31,10 @@
*/
#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
/* some syslogging */
@@ -71,31 +72,39 @@ static int _pam_parse(int argc, const char **argv)
return ctrl;
}
-/* --- authentication management functions (only) --- */
-
-PAM_EXTERN
-int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
- ,const char **argv)
+static int securetty_perform_check(pam_handle_t *pamh, int flags, int ctrl,
+ const char *function_name)
{
int retval = PAM_AUTH_ERR;
const char *username;
char *uttyname;
char ttyfileline[256];
+ char ptname[256];
struct stat ttyfileinfo;
struct passwd *user_pwd;
FILE *ttyfile;
- int ctrl;
- /* parse the arguments */
- ctrl = _pam_parse(argc, argv);
+ /* log a trail for debugging */
+ if (ctrl & PAM_DEBUG_ARG) {
+ _pam_log(LOG_DEBUG, "pam_securetty called via %s function",
+ function_name);
+ }
retval = pam_get_user(pamh, &username, NULL);
if (retval != PAM_SUCCESS || username == NULL) {
if (ctrl & PAM_DEBUG_ARG) {
_pam_log(LOG_WARNING, "cannot determine username");
}
- return (retval == PAM_CONV_AGAIN
- ? PAM_INCOMPLETE:PAM_SERVICE_ERR);
+ return (retval == PAM_CONV_AGAIN ? PAM_INCOMPLETE:PAM_SERVICE_ERR);
+ }
+
+ user_pwd = _pammodutil_getpwnam(pamh, username);
+ if (user_pwd == NULL) {
+ return PAM_IGNORE;
+ } else if (user_pwd->pw_uid != 0) { /* If the user is not root,
+ securetty's does not apply
+ to them */
+ return PAM_SUCCESS;
}
retval = pam_get_item(pamh, PAM_TTY, (const void **)&uttyname);
@@ -107,16 +116,8 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
}
/* The PAM_TTY item may be prefixed with "/dev/" - skip that */
- if (strncmp(TTY_PREFIX, uttyname, sizeof(TTY_PREFIX)-1) == 0)
+ if (strncmp(TTY_PREFIX, uttyname, sizeof(TTY_PREFIX)-1) == 0) {
uttyname += sizeof(TTY_PREFIX)-1;
-
- user_pwd = getpwnam(username);
- if (user_pwd == NULL) {
- return PAM_IGNORE;
- } else if (user_pwd->pw_uid != 0) { /* If the user is not root,
- securetty's does not apply
- to them */
- return PAM_SUCCESS;
}
if (stat(SECURETTY_FILE, &ttyfileinfo)) {
@@ -126,8 +127,7 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
error. */
}
- if ((ttyfileinfo.st_mode & S_IWOTH)
- || !S_ISREG(ttyfileinfo.st_mode)) {
+ if ((ttyfileinfo.st_mode & S_IWOTH) || !S_ISREG(ttyfileinfo.st_mode)) {
/* If the file is world writable or is not a
normal file, return error */
_pam_log(LOG_ERR, SECURETTY_FILE
@@ -136,39 +136,80 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
}
ttyfile = fopen(SECURETTY_FILE,"r");
- if(ttyfile == NULL) { /* Check that we opened it successfully */
+ if (ttyfile == NULL) { /* Check that we opened it successfully */
_pam_log(LOG_ERR,
"Error opening " SECURETTY_FILE);
return PAM_SERVICE_ERR;
}
- /* There should be no more errors from here on */
- retval=PAM_AUTH_ERR;
- /* This loop assumes that PAM_SUCCESS == 0
- and PAM_AUTH_ERR != 0 */
- while((fgets(ttyfileline,sizeof(ttyfileline)-1, ttyfile) != NULL)
- && retval) {
- if(ttyfileline[strlen(ttyfileline) - 1] == '\n')
+
+ if (isdigit(uttyname[0])) {
+ snprintf(ptname, sizeof(ptname), "pts/%s", uttyname);
+ } else {
+ ptname[0] = '\0';
+ }
+
+ retval = 1;
+
+ while ((fgets(ttyfileline, sizeof(ttyfileline)-1, ttyfile) != NULL)
+ && retval) {
+ if (ttyfileline[strlen(ttyfileline) - 1] == '\n')
ttyfileline[strlen(ttyfileline) - 1] = '\0';
- retval = strcmp(ttyfileline,uttyname);
+
+ retval = ( strcmp(ttyfileline, uttyname)
+ && (!ptname[0] || strcmp(ptname, uttyname)) );
}
fclose(ttyfile);
- if(retval) {
- if (ctrl & PAM_DEBUG_ARG)
+
+ if (retval) {
_pam_log(LOG_WARNING, "access denied: tty '%s' is not secure !",
uttyname);
- retval = PAM_AUTH_ERR;
+
+ retval = PAM_AUTH_ERR;
+ } else {
+ if ((retval == PAM_SUCCESS) && (ctrl & PAM_DEBUG_ARG)) {
+ _pam_log(LOG_DEBUG, "access allowed for '%s' on '%s'",
+ username, uttyname);
+ }
+ retval = PAM_SUCCESS;
+
}
- if ((retval == PAM_SUCCESS) && (ctrl & PAM_DEBUG_ARG))
- _pam_log(LOG_DEBUG, "access allowed for '%s' on '%s'",
- username, uttyname);
+
return retval;
}
+/* --- authentication management functions --- */
+
PAM_EXTERN
-int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
- ,const char **argv)
+int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
{
- return PAM_SUCCESS;
+ int ctrl;
+
+ /* parse the arguments */
+ ctrl = _pam_parse(argc, argv);
+
+ return securetty_perform_check(pamh, flags, ctrl, __FUNCTION__);
+}
+
+PAM_EXTERN
+int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return PAM_SUCCESS;
+}
+
+/* --- account management functions --- */
+
+PAM_EXTERN
+int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ int ctrl;
+
+ /* parse the arguments */
+ ctrl = _pam_parse(argc, argv);
+
+ /* take the easy route */
+ return securetty_perform_check(pamh, flags, ctrl, __FUNCTION__);
}
@@ -180,12 +221,12 @@ struct pam_module _pam_securetty_modstruct = {
"pam_securetty",
pam_sm_authenticate,
pam_sm_setcred,
- NULL,
+ pam_sm_acct_mgmt,
NULL,
NULL,
NULL,
};
-#endif
+#endif /* PAM_STATIC */
/* end of module definition */
diff --git a/Linux-PAM/modules/pam_shells/Makefile b/Linux-PAM/modules/pam_shells/Makefile
index 1ead26c5..f1d7ff51 100644
--- a/Linux-PAM/modules/pam_shells/Makefile
+++ b/Linux-PAM/modules/pam_shells/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:33 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_shells/README b/Linux-PAM/modules/pam_shells/README
index cbd5bfb5..aa63a827 100644
--- a/Linux-PAM/modules/pam_shells/README
+++ b/Linux-PAM/modules/pam_shells/README
@@ -1,7 +1,6 @@
pam_shells:
Authentication is granted if the users shell is listed in
- /etc/shells. If no shell is in /etc/passwd (empty), the
- /bin/sh is used (following ftpd's convention).
+ /etc/shells.
Also checks to make sure that /etc/shells is a plain
file and not world writable.
diff --git a/Linux-PAM/modules/pam_shells/pam_shells.c b/Linux-PAM/modules/pam_shells/pam_shells.c
index 36dd1a91..64359eac 100644
--- a/Linux-PAM/modules/pam_shells/pam_shells.c
+++ b/Linux-PAM/modules/pam_shells/pam_shells.c
@@ -12,8 +12,10 @@
#include <pwd.h>
#include <stdarg.h>
+#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/stat.h>
#include <syslog.h>
#include <unistd.h>
@@ -26,8 +28,10 @@
*/
#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
/* some syslogging */
@@ -42,77 +46,98 @@ static void _pam_log(int err, const char *format, ...)
closelog();
}
-/* --- authentication management functions (only) --- */
-
-PAM_EXTERN
-int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
- ,const char **argv)
+static int perform_check(pam_handle_t *pamh, int flags)
{
- int retval = PAM_AUTH_ERR;
- const char *userName;
- char *userShell;
- char shellFileLine[256];
- struct stat sb;
- struct passwd * pw;
- FILE * shellFile;
-
- retval = pam_get_user(pamh,&userName,NULL);
- if(retval != PAM_SUCCESS)
- return PAM_SERVICE_ERR;
-
- if(!userName || (strlen(userName) <= 0)) {
- /* Don't let them use a NULL username... */
- pam_get_user(pamh,&userName,NULL);
+ int retval = PAM_AUTH_ERR;
+ const char *userName;
+ char *userShell;
+ char shellFileLine[256];
+ struct stat sb;
+ struct passwd * pw;
+ FILE * shellFile;
+
+ retval = pam_get_user(pamh, &userName, NULL);
+ if (retval != PAM_SUCCESS) {
+ return PAM_SERVICE_ERR;
+ }
+
+ if (!userName || (userName[0] == '\0')) {
+
+ /* Don't let them use a NULL username... */
+ retval = pam_get_user(pamh,&userName,NULL);
if (retval != PAM_SUCCESS)
- return PAM_SERVICE_ERR;
- }
+ return PAM_SERVICE_ERR;
- pw = getpwnam(userName);
- if (!pw)
+ /* It could still be NULL the second time. */
+ if (!userName || (userName[0] == '\0'))
+ return PAM_SERVICE_ERR;
+ }
+
+ pw = _pammodutil_getpwnam(pamh, userName);
+ if (!pw) {
return PAM_AUTH_ERR; /* user doesn't exist */
- userShell = pw->pw_shell;
+ }
+ userShell = pw->pw_shell;
- if(stat(SHELL_FILE,&sb)) {
- _pam_log(LOG_ERR,
- "%s cannot be stat'd (it probably does not exist)", SHELL_FILE);
+ if (stat(SHELL_FILE,&sb)) {
+ _pam_log(LOG_ERR, "%s cannot be stat'd (it probably does not exist)",
+ SHELL_FILE);
return PAM_AUTH_ERR; /* must have /etc/shells */
- }
+ }
- if((sb.st_mode & S_IWOTH) || !S_ISREG(sb.st_mode)) {
- _pam_log(LOG_ERR,
- "%s is either world writable or not a normal file", SHELL_FILE);
+ if ((sb.st_mode & S_IWOTH) || !S_ISREG(sb.st_mode)) {
+ _pam_log(LOG_ERR, "%s is either world writable or not a normal file",
+ SHELL_FILE);
return PAM_AUTH_ERR;
- }
+ }
- shellFile = fopen(SHELL_FILE,"r");
- if(shellFile == NULL) { /* Check that we opened it successfully */
+ shellFile = fopen(SHELL_FILE,"r");
+ if (shellFile == NULL) { /* Check that we opened it successfully */
_pam_log(LOG_ERR,
- "Error opening %s", SHELL_FILE);
- return PAM_SERVICE_ERR;
- }
- /* There should be no more errors from here on */
- retval=PAM_AUTH_ERR;
- /* This loop assumes that PAM_SUCCESS == 0
- and PAM_AUTH_ERR != 0 */
- while((fgets(shellFileLine,255,shellFile) != NULL)
- && retval) {
- if (shellFileLine[strlen(shellFileLine) - 1] == '\n')
- shellFileLine[strlen(shellFileLine) - 1] = '\0';
- retval = strcmp(shellFileLine, userShell);
- }
- fclose(shellFile);
- if(retval)
- retval = PAM_AUTH_ERR;
- return retval;
+ "Error opening %s", SHELL_FILE);
+ return PAM_SERVICE_ERR;
+ }
+
+ retval = 1;
+
+ while(retval && (fgets(shellFileLine, 255, shellFile) != NULL)) {
+ if (shellFileLine[strlen(shellFileLine) - 1] == '\n')
+ shellFileLine[strlen(shellFileLine) - 1] = '\0';
+ retval = strcmp(shellFileLine, userShell);
+ }
+
+ fclose(shellFile);
+
+ if (retval) {
+ return PAM_AUTH_ERR;
+ } else {
+ return PAM_SUCCESS;
+ }
+}
+
+/* --- authentication management functions (only) --- */
+
+PAM_EXTERN
+int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ return perform_check(pamh, flags);
}
PAM_EXTERN
-int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
- ,const char **argv)
+int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,const char **argv)
{
return PAM_SUCCESS;
}
+/* --- account management functions (only) --- */
+
+PAM_EXTERN
+int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ return perform_check(pamh, flags);
+}
#ifdef PAM_STATIC
@@ -122,12 +147,12 @@ struct pam_module _pam_shells_modstruct = {
"pam_shells",
pam_sm_authenticate,
pam_sm_setcred,
- NULL,
+ pam_sm_acct_mgmt,
NULL,
NULL,
NULL,
};
-#endif
+#endif /* PAM_STATIC */
/* end of module definition */
diff --git a/Linux-PAM/modules/pam_stress/Makefile b/Linux-PAM/modules/pam_stress/Makefile
index 15a891c0..3512c853 100644
--- a/Linux-PAM/modules/pam_stress/Makefile
+++ b/Linux-PAM/modules/pam_stress/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:33 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_stress/README b/Linux-PAM/modules/pam_stress/README
index 7a88f12d..b4273f50 100644
--- a/Linux-PAM/modules/pam_stress/README
+++ b/Linux-PAM/modules/pam_stress/README
@@ -1,5 +1,5 @@
#
-# $Id: README,v 1.1.1.1 2001/04/29 04:17:34 hartmans Exp $
+# $Id: README,v 1.1.1.1 2000/06/20 22:11:57 agmorgan Exp $
#
# This describes the behavior of this module with respect to the
# /etc/pam.conf file.
diff --git a/Linux-PAM/modules/pam_stress/pam_stress.c b/Linux-PAM/modules/pam_stress/pam_stress.c
index 8bc85f5d..2d361c3e 100644
--- a/Linux-PAM/modules/pam_stress/pam_stress.c
+++ b/Linux-PAM/modules/pam_stress/pam_stress.c
@@ -1,6 +1,6 @@
/* pam_stress module */
-/* $Id: pam_stress.c,v 1.1.1.1 2001/04/29 04:17:34 hartmans Exp $
+/* $Id: pam_stress.c,v 1.4 2004/09/22 09:37:50 kukuk Exp $
*
* created by Andrew Morgan <morgan@linux.kernel.org> 1996/3/12
*/
@@ -10,7 +10,6 @@
#include <stdlib.h>
#include <stdio.h>
-#define __USE_BSD
#include <syslog.h>
#include <stdarg.h>
@@ -32,13 +31,6 @@
#include <security/pam_modules.h>
#include <security/_pam_macros.h>
-static char *_strdup(const char *x)
-{
- char *new;
- new = malloc(strlen(x)+1);
- strcpy(new,x);
- return new;
-}
/* log errors */
@@ -142,8 +134,8 @@ static int converse(pam_handle_t *pamh, int nargs
int retval;
struct pam_conv *conv;
- if ((retval = pam_get_item(pamh,PAM_CONV,(const void **)&conv))
- == PAM_SUCCESS) {
+ retval = pam_get_item(pamh,PAM_CONV,(const void **)&conv);
+ if (retval == PAM_SUCCESS && conv) {
retval = conv->conv(nargs, (const struct pam_message **) message
, response, conv->appdata_ptr);
if (retval != PAM_SUCCESS) {
@@ -152,6 +144,8 @@ static int converse(pam_handle_t *pamh, int nargs
}
} else {
_pam_log(LOG_ERR,"(pam_stress) converse failed to get pam_conv");
+ if (retval == PAM_SUCCESS)
+ retval = PAM_BAD_ITEM; /* conv was null */
}
return retval;
@@ -168,7 +162,8 @@ static int stress_get_password(pam_handle_t *pamh, int flags
&& (pam_get_item(pamh,PAM_AUTHTOK,(const void **)&pass)
== PAM_SUCCESS)
&& (pass != NULL) ) {
- pass = _strdup(pass);
+ if ((pass = strdup(pass)) == NULL)
+ return PAM_BUF_ERR;
} else if ((ctrl & PAM_ST_USE_PASS1)) {
_pam_log(LOG_WARNING, "pam_stress: no forwarded password");
return PAM_PERM_DENIED;
@@ -207,7 +202,8 @@ static int stress_get_password(pam_handle_t *pamh, int flags
_pam_log(LOG_DEBUG,"getting password, but NULL returned!?");
return PAM_CONV_ERR;
}
- free(resp);
+ if (resp)
+ free(resp);
}
*password = pass; /* this *MUST* be free()'d by this module */
@@ -239,12 +235,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
/* try to get the username */
retval = pam_get_user(pamh, &username, "username: ");
- if ((ctrl & PAM_ST_DEBUG) && (retval == PAM_SUCCESS)) {
- _pam_log(LOG_DEBUG, "pam_sm_authenticate: username = %s", username);
- } else if (retval != PAM_SUCCESS) {
+ if (retval != PAM_SUCCESS || !username) {
_pam_log(LOG_WARNING, "pam_sm_authenticate: failed to get username");
+ if (retval == PAM_SUCCESS)
+ retval = PAM_USER_UNKNOWN; /* username was null */
return retval;
}
+ else if ((ctrl & PAM_ST_DEBUG) && (retval == PAM_SUCCESS)) {
+ _pam_log(LOG_DEBUG, "pam_sm_authenticate: username = %s", username);
+ }
/* now get the password */
@@ -258,20 +257,15 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
/* try to set password item */
retval = pam_set_item(pamh,PAM_AUTHTOK,pass);
+ _pam_overwrite(pass); /* clean up local copy of password */
+ free(pass);
+ pass = NULL;
if (retval != PAM_SUCCESS) {
_pam_log(LOG_WARNING, "pam_sm_authenticate: "
"failed to store new password");
- _pam_overwrite(pass);
- free(pass);
return retval;
}
- /* clean up local copy of password */
-
- _pam_overwrite(pass);
- free(pass);
- pass = NULL;
-
/* if we are debugging then we print the password */
if (ctrl & PAM_ST_DEBUG) {
@@ -320,9 +314,18 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
if (ctrl & PAM_ST_FAIL_1)
return PAM_PERM_DENIED;
else if (ctrl & PAM_ST_EXPIRED) {
- void *text = malloc(sizeof("yes")+1);
- strcpy(text,"yes");
- pam_set_data(pamh,"stress_new_pwd",text,wipe_up);
+ int retval;
+ void *text = strdup("yes");
+ if (!text)
+ return PAM_BUF_ERR;
+ retval = pam_set_data(pamh,"stress_new_pwd",text,wipe_up);
+ if (retval != PAM_SUCCESS) {
+ _pam_log(LOG_DEBUG,
+ "pam_sm_acct_mgmt: failed setting stress_new_pwd");
+ free(text);
+ return retval;
+ }
+
if (ctrl & PAM_ST_DEBUG) {
_pam_log(LOG_DEBUG,"pam_sm_acct_mgmt: need a new password");
}
@@ -344,9 +347,9 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
_pam_report(ctrl,"pam_sm_open_session", flags, argc, argv);
if ((pam_get_item(pamh, PAM_USER, (const void **) &username)
- != PAM_SUCCESS)
+ != PAM_SUCCESS || !username)
|| (pam_get_item(pamh, PAM_SERVICE, (const void **) &service)
- != PAM_SUCCESS)) {
+ != PAM_SUCCESS || !service)) {
_pam_log(LOG_WARNING,"pam_sm_open_session: for whom?");
return PAM_SESSION_ERR;
}
@@ -372,9 +375,9 @@ int pam_sm_close_session(pam_handle_t *pamh, int flags,
_pam_report(ctrl,"pam_sm_close_session", flags, argc, argv);
if ((pam_get_item(pamh, PAM_USER, (const void **)&username)
- != PAM_SUCCESS)
+ != PAM_SUCCESS || !username)
|| (pam_get_item(pamh, PAM_SERVICE, (const void **)&service)
- != PAM_SUCCESS)) {
+ != PAM_SUCCESS || !service)) {
_pam_log(LOG_WARNING,"pam_sm_close_session: for whom?");
return PAM_SESSION_ERR;
}
@@ -448,15 +451,14 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
return retval;
}
retval = pam_set_item(pamh, PAM_OLDAUTHTOK, pass);
+ _pam_overwrite(pass);
+ free(pass);
+ pass = NULL;
if (retval != PAM_SUCCESS) {
_pam_log(LOG_DEBUG
,"pam_sm_chauthtok: could not set OLDAUTHTOK");
- _pam_overwrite(pass);
- free(pass);
return retval;
}
- _pam_overwrite(pass);
- free(pass);
}
/* set up for conversation */
@@ -517,7 +519,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
pmsg[0] = &msg[0];
msg[0].msg_style = PAM_ERROR_MSG;
msg[0].msg = "Verification mis-typed; "
- "password unchaged";
+ "password unchanged";
resp = NULL;
(void) converse(pamh,1,pmsg,&resp);
if (resp) {
diff --git a/Linux-PAM/modules/pam_succeed_if/Makefile b/Linux-PAM/modules/pam_succeed_if/Makefile
new file mode 100644
index 00000000..cea9be3b
--- /dev/null
+++ b/Linux-PAM/modules/pam_succeed_if/Makefile
@@ -0,0 +1,16 @@
+#
+# $Id: Makefile,v 1.1 2004/09/24 11:42:39 kukuk Exp $
+#
+# This Makefile controls a build process of $(TITLE) module for
+# Linux-PAM. You should not modify this Makefile (unless you know
+# what you are doing!).
+#
+# Created by Andrew Morgan <morgan@linux.kernel.org> 2000/08/27
+#
+
+include ../../Make.Rules
+
+TITLE=pam_succeed_if
+MAN8=$(TITLE).8
+
+include ../Simple.Rules
diff --git a/Linux-PAM/modules/pam_succeed_if/README b/Linux-PAM/modules/pam_succeed_if/README
new file mode 100644
index 00000000..fdb278ef
--- /dev/null
+++ b/Linux-PAM/modules/pam_succeed_if/README
@@ -0,0 +1,68 @@
+pam_succeed_if:
+ Succeed or fail based on account characteristics.
+
+ pam_succeed_if.so is designed to succeed or fail authentication based
+ on characteristics of the account belonging to the user being
+ authenticated.
+
+ The module can be given one or more conditions as module arguments, and
+ authentication will succeed only if all of the conditions are met.
+
+ Conditions are expressed in the form
+
+ ATTRIBUTE OPERATOR VALUE
+
+ Recognized attributes:
+
+ LOGIN - The user's login name.
+ UID - The user's UID.
+ GID - The user's primary GID.
+ SHELL - The user's shell.
+ HOME - The user's home directory.
+
+ Recognized operators:
+
+ < - Arithmetic less-than.
+ <= - Arithmetic less-than-or-equal-to.
+ > - Arithmetic greater-than.
+ >= - Arithmetic greater-than-or-equal-to.
+ eq - Arithmetic equality.
+ = - String equality.
+ ne - Arithmetic inequality.
+ != - String inequality.
+ =~ - Wildcard match.
+ !~ - Wildcard mismatch.
+ ingroup - Group membership check. [*]
+ notingroup - Group non-membership check. [*]
+
+ * The "ingroup" and "notingroup" operators should only be
+ used with the USER attribute.
+
+ Examples:
+
+ Deny authentication to all users except those in the wheel
+ group, before even asking for a password:
+ auth requisite pam_succeed_if.so user ingroup wheel
+
+ Assume all users with UID less than 500 ("system users") have
+ valid accounts.
+ account sufficient pam_succeed_if.so uid < 500
+
+ Deny login to all nologin users.
+ auth requisite pam_succeed_if.so shell !~ nologin
+
+RECOGNIZED ARGUMENTS:
+ debug write debugging messages to syslog
+ use_uid perform checks on the account of the user under whose
+ UID the application is running instead of the user
+ being authenticated
+ quiet don't log failure or success to syslog
+ quiet_fail don't log failure to syslog
+ quiet_success don't log success to syslog
+
+
+MODULE SERVICES PROVIDED:
+ authentication, account management
+
+AUTHOR:
+ Nalin Dahyabhai <nalin@redhat.com>
diff --git a/Linux-PAM/modules/pam_succeed_if/pam_succeed_if.8 b/Linux-PAM/modules/pam_succeed_if/pam_succeed_if.8
new file mode 100644
index 00000000..da95a033
--- /dev/null
+++ b/Linux-PAM/modules/pam_succeed_if/pam_succeed_if.8
@@ -0,0 +1,37 @@
+.\" Copyright 2003, 2004 Red Hat, Inc.
+.\" Written by Nalin Dahyabhai <nalin@redhat.com>
+.TH pam_succeed_if 8 2004/12/27 "Linux-PAM" "System Administrator's Manual"
+
+.SH NAME
+pam_succeed_if \- succeed or fail based on account characteristics
+
+.SH SYNOPSIS
+.B account sufficient pam_succeed_if.so uid < 500
+
+.SH DESCRIPTION
+pam_succeed_if.so is designed to succeed or fail authentication based on
+characteristics of the account belonging to the user being authenticated.
+
+The module can be given one or more conditions as module arguments, and
+authentication will succeed only if all of the conditions are met.
+
+.SH ARGUMENTS
+.IP debug
+Turns on debugging messages sent to syslog.
+.IP use_uid
+Evaluate conditions using the account of the user whose UID the application
+is running under instead of the user being authenticated.
+.IP quiet
+Don't log failure or success to the system log.
+.IP quiet_fail
+Don't log failure to the system log.
+.IP quiet_success
+Don't log success to the system log.
+
+
+.SH BUGS
+Let's hope not, but if you find any, please report them via the "Bug Track"
+link at http://bugzilla.redhat.com/bugzilla/
+
+.SH AUTHOR
+Nalin Dahyabhai <nalin@redhat.com>
diff --git a/Linux-PAM/modules/pam_succeed_if/pam_succeed_if.c b/Linux-PAM/modules/pam_succeed_if/pam_succeed_if.c
new file mode 100644
index 00000000..23974afa
--- /dev/null
+++ b/Linux-PAM/modules/pam_succeed_if/pam_succeed_if.c
@@ -0,0 +1,470 @@
+/******************************************************************************
+ * A simple user-attribute based module for PAM.
+ *
+ * Copyright (c) 2003 Red Hat, Inc.
+ * Written by Nalin Dahyabhai <nalin@redhat.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
+
+#define MODULE "pam_succeed_if"
+
+static void
+log_error(int priority, const char *fmt, ...)
+{
+ va_list va;
+ char *fmt2;
+ fmt2 = malloc(strlen(fmt) + strlen(MODULE) + 3);
+ va_start(va, fmt);
+ if (fmt2 == NULL) {
+ vsyslog(LOG_AUTHPRIV | priority, fmt, va);
+ } else {
+ snprintf(fmt2, strlen(fmt) + strlen(MODULE) + 3,
+ "%s: %s", MODULE, fmt);
+ vsyslog(LOG_AUTHPRIV | priority, fmt2, va);
+ free(fmt2);
+ }
+ va_end(va);
+}
+
+/* Basically, run cmp(atol(left), atol(right)), returning PAM_SUCCESS if
+ * the function returns non-zero, PAM_AUTH_ERR if it returns zero, and
+ * PAM_SYSTEM_ERR if the arguments can't be parsed as numbers. */
+static int
+evaluate_num(const char *left, const char *right, int (*cmp)(int, int))
+{
+ long l, r;
+ char *p;
+ int ret = PAM_SUCCESS;
+
+ errno = 0;
+ l = strtol(left, &p, 0);
+ if ((p == NULL) || (*p != '\0') || errno) {
+ log_error(LOG_INFO, "\"%s\" is not a number", left);
+ ret = PAM_SERVICE_ERR;
+ }
+
+ r = strtol(right, &p, 0);
+ if ((p == NULL) || (*p != '\0') || errno) {
+ log_error(LOG_INFO, "\"%s\" is not a number", right);
+ ret = PAM_SERVICE_ERR;
+ }
+
+ if (ret != PAM_SUCCESS) {
+ return ret;
+ }
+
+ return cmp(l, r) ? PAM_SUCCESS : PAM_AUTH_ERR;
+}
+
+/* Simple numeric comparison callbacks. */
+static int
+eq(int i, int j)
+{
+ return i == j;
+}
+static int
+ne(int i, int j)
+{
+ return i != j;
+}
+static int
+lt(int i, int j)
+{
+ return i < j;
+}
+static int
+le(int i, int j)
+{
+ return lt(i, j) || eq(i, j);
+}
+static int
+gt(int i, int j)
+{
+ return i > j;
+}
+static int
+ge(int i, int j)
+{
+ return gt(i, j) || eq(i, j);
+}
+
+/* Test for numeric equality. */
+static int
+evaluate_eqn(const char *left, const char *right)
+{
+ return evaluate_num(left, right, eq);
+}
+/* Test for string equality. */
+static int
+evaluate_eqs(const char *left, const char *right)
+{
+ return (strcmp(left, right) == 0) ? PAM_SUCCESS : PAM_AUTH_ERR;
+}
+/* Test for numeric inequality. */
+static int
+evaluate_nen(const char *left, const char *right)
+{
+ return evaluate_num(left, right, ne);
+}
+/* Test for string inequality. */
+static int
+evaluate_nes(const char *left, const char *right)
+{
+ return (strcmp(left, right) != 0) ? PAM_SUCCESS : PAM_AUTH_ERR;
+}
+/* Test for numeric less-than-ness(?) */
+static int
+evaluate_lt(const char *left, const char *right)
+{
+ return evaluate_num(left, right, lt);
+}
+/* Test for numeric less-than-or-equal-ness(?) */
+static int
+evaluate_le(const char *left, const char *right)
+{
+ return evaluate_num(left, right, le);
+}
+/* Test for numeric greater-than-ness(?) */
+static int
+evaluate_gt(const char *left, const char *right)
+{
+ return evaluate_num(left, right, gt);
+}
+/* Test for numeric greater-than-or-equal-ness(?) */
+static int
+evaluate_ge(const char *left, const char *right)
+{
+ return evaluate_num(left, right, ge);
+}
+/* Check for file glob match. */
+static int
+evaluate_glob(const char *left, const char *right)
+{
+ return (fnmatch(right, left, 0) == 0) ? PAM_SUCCESS : PAM_AUTH_ERR;
+}
+/* Check for file glob mismatch. */
+static int
+evaluate_noglob(const char *left, const char *right)
+{
+ return (fnmatch(right, left, 0) != 0) ? PAM_SUCCESS : PAM_AUTH_ERR;
+}
+/* Return PAM_SUCCESS if the user is in the group. */
+static int
+evaluate_ingroup(pam_handle_t *pamh, const char *user, const char *group)
+{
+ int ret;
+ ret = _pammodutil_user_in_group_nam_nam(pamh, user, group);
+ switch (ret) {
+ case 1:
+ return PAM_SUCCESS;
+ break;
+ default:
+ break;
+ }
+ return PAM_AUTH_ERR;
+}
+/* Return PAM_SUCCESS if the user is NOT in the group. */
+static int
+evaluate_notingroup(pam_handle_t *pamh, const char *user, const char *group)
+{
+ int ret;
+ ret = _pammodutil_user_in_group_nam_nam(pamh, user, group);
+ switch (ret) {
+ case 0:
+ return PAM_SUCCESS;
+ break;
+ default:
+ break;
+ }
+ return PAM_AUTH_ERR;
+}
+
+/* Match a triple. */
+static int
+evaluate(pam_handle_t *pamh, int debug,
+ const char *left, const char *qual, const char *right,
+ struct passwd *pwd)
+{
+ char buf[LINE_MAX] = "";
+ const char *attribute = left;
+ /* Figure out what we're evaluating here, and convert it to a string.*/
+ if ((strcasecmp(left, "login") == 0) ||
+ (strcasecmp(left, "name") == 0) ||
+ (strcasecmp(left, "user") == 0)) {
+ snprintf(buf, sizeof(buf), "%s", pwd->pw_name);
+ left = buf;
+ }
+ if (strcasecmp(left, "uid") == 0) {
+ snprintf(buf, sizeof(buf), "%lu", (unsigned long) pwd->pw_uid);
+ left = buf;
+ }
+ if (strcasecmp(left, "gid") == 0) {
+ snprintf(buf, sizeof(buf), "%lu", (unsigned long) pwd->pw_gid);
+ left = buf;
+ }
+ if (strcasecmp(left, "shell") == 0) {
+ snprintf(buf, sizeof(buf), "%s", pwd->pw_shell);
+ left = buf;
+ }
+ if ((strcasecmp(left, "home") == 0) ||
+ (strcasecmp(left, "dir") == 0) ||
+ (strcasecmp(left, "homedir") == 0)) {
+ snprintf(buf, sizeof(buf), "%s", pwd->pw_dir);
+ left = buf;
+ }
+ /* If we have no idea what's going on, return an error. */
+ if (left != buf) {
+ log_error(LOG_CRIT, "unknown attribute \"%s\"", left);
+ return PAM_SERVICE_ERR;
+ }
+ if (debug) {
+ log_error(LOG_DEBUG, "'%s' resolves to '%s'", attribute, left);
+ }
+
+ /* Attribute value < some threshold. */
+ if ((strcasecmp(qual, "<") == 0) ||
+ (strcasecmp(qual, "lt") == 0)) {
+ return evaluate_lt(left, right);
+ }
+ /* Attribute value <= some threshold. */
+ if ((strcasecmp(qual, "<=") == 0) ||
+ (strcasecmp(qual, "le") == 0)) {
+ return evaluate_le(left, right);
+ }
+ /* Attribute value > some threshold. */
+ if ((strcasecmp(qual, ">") == 0) ||
+ (strcasecmp(qual, "gt") == 0)) {
+ return evaluate_gt(left, right);
+ }
+ /* Attribute value >= some threshold. */
+ if ((strcasecmp(qual, ">=") == 0) ||
+ (strcasecmp(qual, "ge") == 0)) {
+ return evaluate_ge(left, right);
+ }
+ /* Attribute value == some threshold. */
+ if (strcasecmp(qual, "eq") == 0) {
+ return evaluate_eqn(left, right);
+ }
+ /* Attribute value = some string. */
+ if (strcasecmp(qual, "=") == 0) {
+ return evaluate_eqs(left, right);
+ }
+ /* Attribute value != some threshold. */
+ if (strcasecmp(qual, "ne") == 0) {
+ return evaluate_nen(left, right);
+ }
+ /* Attribute value != some string. */
+ if (strcasecmp(qual, "!=") == 0) {
+ return evaluate_nes(left, right);
+ }
+ /* Attribute value matches some pattern. */
+ if ((strcasecmp(qual, "=~") == 0) ||
+ (strcasecmp(qual, "glob") == 0)) {
+ return evaluate_glob(left, right);
+ }
+ if ((strcasecmp(qual, "!~") == 0) ||
+ (strcasecmp(qual, "noglob") == 0)) {
+ return evaluate_noglob(left, right);
+ }
+ /* User is in this group. */
+ if (strcasecmp(qual, "ingroup") == 0) {
+ return evaluate_ingroup(pamh, pwd->pw_name, right);
+ }
+ /* User is not in this group. */
+ if (strcasecmp(qual, "notingroup") == 0) {
+ return evaluate_notingroup(pamh, pwd->pw_name, right);
+ }
+ /* Fail closed. */
+ return PAM_SERVICE_ERR;
+}
+
+int
+pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ const char *prompt;
+ const char *user;
+ struct passwd *pwd;
+ int ret, i, count, use_uid, debug;
+ const char *left, *right, *qual;
+ int quiet_fail, quiet_succ;
+
+ /* Get the user prompt. */
+ ret = pam_get_item(pamh, PAM_USER_PROMPT, (const void**) &prompt);
+ if ((ret != PAM_SUCCESS) || (prompt == NULL) || (strlen(prompt) == 0)) {
+ prompt = "login: ";
+ }
+
+ quiet_fail = 0;
+ quiet_succ = 0;
+ for (use_uid = 0, debug = 0, i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "debug") == 0) {
+ debug++;
+ }
+ if (strcmp(argv[i], "use_uid") == 0) {
+ use_uid++;
+ }
+ if (strcmp(argv[i], "quiet") == 0) {
+ quiet_fail++;
+ quiet_succ++;
+ }
+ if (strcmp(argv[i], "quiet_fail") == 0) {
+ quiet_fail++;
+ }
+ if (strcmp(argv[i], "quiet_success") == 0) {
+ quiet_succ++;
+ }
+ }
+
+ if (use_uid) {
+ /* Get information about the user. */
+ pwd = _pammodutil_getpwuid(pamh, getuid());
+ if (pwd == NULL) {
+ log_error(LOG_CRIT,
+ "error retrieving information about user %ld",
+ (long)getuid());
+ return PAM_SERVICE_ERR;
+ }
+ } else {
+ /* Get the user's name. */
+ ret = pam_get_user(pamh, &user, prompt);
+ if ((ret != PAM_SUCCESS) || (user == NULL)) {
+ log_error(LOG_CRIT, "error retrieving user name: %s",
+ pam_strerror(pamh, ret));
+ return ret;
+ }
+
+ /* Get information about the user. */
+ pwd = _pammodutil_getpwnam(pamh, user);
+ if (pwd == NULL) {
+ log_error(LOG_CRIT,
+ "error retrieving information about user %s",
+ user);
+ return PAM_SERVICE_ERR;
+ }
+ }
+
+ /* Walk the argument list. */
+ i = count = 0;
+ left = qual = right = NULL;
+ while (i <= argc) {
+ if ((left != NULL) && (qual != NULL) && (right != NULL)) {
+ ret = evaluate(pamh, debug,
+ left, qual, right,
+ pwd);
+ if (ret != PAM_SUCCESS) {
+ if(!quiet_fail)
+ log_error(LOG_INFO,
+ "requirement \"%s %s %s\" "
+ "not met by user \"%s\"",
+ left, qual, right, user);
+ break;
+ }
+ else
+ if(!quiet_succ)
+ log_error(LOG_INFO,
+ "requirement \"%s %s %s\" "
+ "was met by user \"%s\"",
+ left, qual, right, user);
+ left = qual = right = NULL;
+ }
+ if ((i < argc) && (strcmp(argv[i], "debug") == 0)) {
+ i++;
+ continue;
+ }
+ if ((i < argc) && (strcmp(argv[i], "use_uid") == 0)) {
+ i++;
+ continue;
+ }
+ if ((i < argc) && (strcmp(argv[i], "quiet") == 0)) {
+ i++;
+ continue;
+ }
+ if ((i < argc) && (strcmp(argv[i], "quiet_fail") == 0)) {
+ i++;
+ continue;
+ }
+ if ((i < argc) && (strcmp(argv[i], "quiet_success") == 0)) {
+ i++;
+ continue;
+ }
+ if ((i < argc) && (left == NULL)) {
+ left = argv[i++];
+ count++;
+ continue;
+ }
+ if ((i < argc) && (qual == NULL)) {
+ qual = argv[i++];
+ count++;
+ continue;
+ }
+ if ((i < argc) && (right == NULL)) {
+ right = argv[i++];
+ count++;
+ continue;
+ }
+ i++;
+ }
+
+ return ret;
+}
+
+int
+pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return PAM_SUCCESS;
+}
+
+int
+pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return pam_sm_authenticate(pamh, flags, argc, argv);
+}
diff --git a/Linux-PAM/modules/pam_tally/Makefile b/Linux-PAM/modules/pam_tally/Makefile
index d173b080..40617a1a 100644
--- a/Linux-PAM/modules/pam_tally/Makefile
+++ b/Linux-PAM/modules/pam_tally/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.2 2002/09/15 20:08:58 hartmans Exp $
+# $Id: Makefile,v 1.5 2004/09/24 13:13:21 kukuk Exp $
#
# This Makefile controls a build process of $(TITLE) module and
# application for Linux-PAM. You should not modify this Makefile
@@ -44,6 +44,12 @@ endif
APPLICATION = $(TITLE)
APPMODE = 755
+LINK_PAMMODUTILS = -L../pammodutil -lpammodutil -L../../libpam -lpam
+INCLUDE_PAMMODUTILS = -I../pammodutil/include
+
+LDFLAGS += $(LINK_PAMMODUTILS)
+CFLAGS += $(INCLUDE_PAMMODUTILS)
+
####################### don't edit below #######################
all: dirs $(LIBSHARED) $(LIBSTATIC) register $(APPLICATION)
@@ -65,10 +71,10 @@ ifdef DYNAMIC
$(LIBOBJD): $(LIBSRC)
$(LIBSHARED): $(LIBOBJD)
- $(LD_D) -o $@ $(LIBOBJD)
+ $(LD_D) -o $@ $(LIBOBJD) $(LDFLAGS)
$(APPLICATION): $(APPOBJD) $(TITLE).c
- $(CC) $(CFLAGS) -o $@ $(APPOBJD) $(LOADLIBES)
+ $(CC) $(CFLAGS) -o $@ $(APPOBJD) $(LDFLAGS) $(LOADLIBES)
endif
diff --git a/Linux-PAM/modules/pam_tally/README b/Linux-PAM/modules/pam_tally/README
index 4c421648..c8b715bd 100644
--- a/Linux-PAM/modules/pam_tally/README
+++ b/Linux-PAM/modules/pam_tally/README
@@ -1,5 +1,5 @@
SUMMARY:
- pam_tally:
+ pam_tally.so:
Maintains a count of attempted accesses, can reset count on success,
can deny access if too many attempts fail.
@@ -9,43 +9,57 @@ SUMMARY:
* onerr=[succeed|fail] (if something weird happens
such as unable to open the file, what to do?)
* file=/where/to/keep/counts (default /var/log/faillog)
+ * audit (will display the username typed if the user is not found)
(auth)
- Authentication phase increments attempted login counter.
- * no_magic_root (root DOES increment counter. Use for
- daemon-based stuff, like telnet/rsh/login)
+ Authentication phase first checks if user should be denied access
+ and if not it increments attempted login counter. Then on call to
+ pam_setcred it resets the attempts counter if the user is NOT
+ magic root.
+ * deny=n (deny access if tally for this user exceeds n)
+
+ * lock_time=n (always deny for n seconds after failed attempt)
+
+ * unlock_time=n (allow access after n seconds after the last
+ failed attempt with exceeded tally)
- (account)
- Account phase can deny access and/or reset attempts counter.
- * deny=n (deny access if tally for this user exceeds n;
- The presence of deny=n changes the default for
- reset/no_reset to reset, unless the user trying to
- gain access is root and the no_magic_root option
- has NOT been specified.)
-
- * no_magic_root (access attempts by root DON'T ignore deny.
- Use this for daemon-based stuff, like telnet/rsh/login)
+ * magic_root (access attempts by root as requesting user ignore
+ deny and don't change counter.
+ Use this for su and similar services.)
+
* even_deny_root_account (Root can become unavailable. BEWARE.
Note that magic root trying to gain root bypasses this,
but normal users can be locked out.)
- * reset (reset count to 0 on successful entry, even for
- magic root)
- * no_reset (don't reset count on successful entry)
- This is the default unless deny exists and the
- user attempting access is NOT magic root.
-
* per_user (If /var/log/faillog contains a non-zero
- .fail_max field for this user then use it
- instead of deny=n parameter)
+ .fail_max/.fail_locktime field for this user then use it
+ instead of deny=n/lock_time=n parameter.)
* no_lock_time (Don't use .fail_locktime filed in
/var/log/faillog for this user)
+ * no_reset (don't reset count on successful entry,
+ only decrement)
+
+
+ (account)
+ Account phase resets attempts counter if the user is NOT magic root.
+ This phase can be used optionaly for services which don't call
+ pam_setcred correctly or if the reset should be done regardless
+ of the failure of the account phase of other modules.
+
+ * magic_root (access attempts by root as requesting user
+ don't change counter.
+ Use this for su and similar services.)
+
+ * no_reset (don't reset count on successful entry,
+ only decrement)
+
Also checks to make sure that the counts file is a plain
file and not world writable.
- Tim Baverstock <warwick@sable.demon.co.uk>, v0.1 5 March 1997
+ - Tomas Mraz <tmraz@redhat.com>, v0.2 5 January 2005
LONGER:
@@ -53,20 +67,20 @@ pam_tally comes in two parts: pam_tally.so and pam_tally.
pam_tally.so sits in a pam config file, in the auth and account sections.
-In the auth section, it increments a per-uid counter for each attempted
-login, in the account section, it denies access if attempted logins
-exceed some threashold and/or resets that counter to zero on successful
-login.
+In the auth section, it denies access if attempted logins exceed some
+threshold and it increments a per-uid counter for each attempted login,
+in the account section, it resets that counter to zero on successful
+login. If the module isn't used in the account section it resets the counter
+to zero on call to pam_setcred.
Root is treated specially:
-1. When a process already running as root tries to access some service, the
-access is `magic', and bypasses pam_tally's checks: handy for `su'ing from
-root into an account otherwise blocked. However, for services like telnet or
-login which always effectively run from the root account, root (ie everyone)
-shouldn't be granted this magic status, and the flag `no_magic_root' should
-be set in this situation, as noted in the summary above. [This option may
-be obsolete, with `sufficient root' processing.]
+1. When a process already running as root tries to access some service and the
+'magic_root' flag is set, the access is `magic', and bypasses pam_tally's
+checks: handy for `su'ing from root into an account otherwise blocked.
+NOTE: This was changed from the previous version of pam_tally where the default
+was to treat root as magic and there were the 'no_magic_root' flag. However
+for most of services the current default make sense.
2. Normally, failed attempts to access root will NOT cause the root
account to become blocked, to prevent denial-of-service: if your users aren't
@@ -93,3 +107,10 @@ The (4.0 Redhat) utilities seem to do funny things with uid, and I'm
not wholly sure I understood what I should have been doing anyway so
the `keep a count of current logins' bit has been #ifdef'd out and you
can only reset the counter on successful authentication, for now.
+
+IMPORTANT NOTICE:
+In the original version of pam_tally there was a bug where the information
+if the password was correct or not was leaked by returning error from
+different pam management phases. This was solved by moving the denying
+functionality to the auth phase. However it's necessary to update the pam
+configuration by moving the required options (as deny=N) to the auth phase.
diff --git a/Linux-PAM/modules/pam_tally/faillog.h b/Linux-PAM/modules/pam_tally/faillog.h
index fa9c414f..0f16261b 100644
--- a/Linux-PAM/modules/pam_tally/faillog.h
+++ b/Linux-PAM/modules/pam_tally/faillog.h
@@ -30,7 +30,7 @@
/*
* faillog.h - login failure logging file format
*
- * $Id: faillog.h,v 1.1.1.1 2001/04/29 04:17:35 hartmans Exp $
+ * $Id: faillog.h,v 1.1.1.1 2000/06/20 22:11:59 agmorgan Exp $
*
* The login failure file is maintained by login(1) and faillog(8)
* Each record in the file represents a separate UID and the file
diff --git a/Linux-PAM/modules/pam_tally/pam_tally.c b/Linux-PAM/modules/pam_tally/pam_tally.c
index a2fed80b..1e48662e 100644
--- a/Linux-PAM/modules/pam_tally/pam_tally.c
+++ b/Linux-PAM/modules/pam_tally/pam_tally.c
@@ -1,7 +1,7 @@
/*
* pam_tally.c
*
- * $Id: pam_tally.c,v 1.1.1.2 2002/09/15 20:08:59 hartmans Exp $
+ * $Id: pam_tally.c,v 1.15 2005/01/24 14:04:17 t8m Exp $
*/
@@ -9,6 +9,9 @@
* 5 March 1997
*
* Stuff stolen from pam_rootok and pam_listfile
+ *
+ * Changes by Tomas Mraz <tmraz@redhat.com> 5 January 2005
+ * Audit option added for Tomas patch by Sebastien Tricaud <toady@gscore.org> 13 January 2005
*/
#include <security/_pam_aconf.h>
@@ -49,18 +52,13 @@
/* #define PAM_SM_PASSWORD */
#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
/*---------------------------------------------------------------------*/
#define DEFAULT_LOGFILE "/var/log/faillog"
#define MODULE_NAME "pam_tally"
-enum TALLY_RESET {
- TALLY_RESET_DEFAULT,
- TALLY_RESET_RESET,
- TALLY_RESET_NO_RESET
-};
-
#define tally_t unsigned short int
#define TALLY_FMT "%hu"
#define TALLY_HI ((tally_t)~0L)
@@ -78,6 +76,28 @@ struct fail_s {
#endif /* ndef MAIN */
};
+struct tally_options {
+ const char *filename;
+ tally_t deny;
+ long lock_time;
+ long unlock_time;
+ unsigned int ctrl;
+};
+
+#define PHASE_UNKNOWN 0
+#define PHASE_AUTH 1
+#define PHASE_ACCOUNT 2
+#define PHASE_SESSION 3
+
+#define OPT_MAGIC_ROOT 01
+#define OPT_FAIL_ON_ERROR 02
+#define OPT_DENY_ROOT 04
+#define OPT_PER_USER 010
+#define OPT_NO_LOCK_TIME 020
+#define OPT_NO_RESET 040
+#define OPT_AUDIT 100
+
+
/*---------------------------------------------------------------------*/
/* some syslogging */
@@ -100,6 +120,94 @@ static void _pam_log(int err, const char *format, ...)
/*---------------------------------------------------------------------*/
+/* --- Support function: parse arguments --- */
+
+static void log_phase_no_auth( int phase, const char *argv )
+{
+ if ( phase != PHASE_AUTH ) {
+ _pam_log(LOG_ERR,
+ MODULE_NAME ": option %s allowed in auth phase only", argv);
+ }
+}
+
+static int tally_parse_args( struct tally_options *opts, int phase,
+ int argc, const char **argv )
+{
+ memset(opts, 0, sizeof(*opts));
+ opts->filename = DEFAULT_LOGFILE;
+
+ for ( ; argc-- > 0; ++argv ) {
+
+ if ( ! strncmp( *argv, "file=", 5 ) ) {
+ const char *from = *argv + 5;
+ if ( *from!='/' || strlen(from)>FILENAME_MAX-1 ) {
+ _pam_log(LOG_ERR,
+ MODULE_NAME ": filename not /rooted or too long; ",
+ *argv);
+ return PAM_AUTH_ERR;
+ }
+ opts->filename = from;
+ }
+ else if ( ! strcmp( *argv, "onerr=fail" ) ) {
+ opts->ctrl |= OPT_FAIL_ON_ERROR;
+ }
+ else if ( ! strcmp( *argv, "onerr=succeed" ) ) {
+ opts->ctrl &= ~OPT_FAIL_ON_ERROR;
+ }
+ else if ( ! strcmp( *argv, "magic_root" ) ) {
+ opts->ctrl |= OPT_MAGIC_ROOT;
+ }
+ else if ( ! strcmp( *argv, "even_deny_root_account" ) ) {
+ log_phase_no_auth(phase, *argv);
+ opts->ctrl |= OPT_DENY_ROOT;
+ }
+ else if ( ! strncmp( *argv, "deny=", 5 ) ) {
+ log_phase_no_auth(phase, *argv);
+ if ( sscanf((*argv)+5,TALLY_FMT,&opts->deny) != 1 ) {
+ _pam_log(LOG_ERR,"bad number supplied; %s",*argv);
+ return PAM_AUTH_ERR;
+ }
+ }
+ else if ( ! strncmp( *argv, "lock_time=", 10 ) ) {
+ log_phase_no_auth(phase, *argv);
+ if ( sscanf((*argv)+10,"%ld",&opts->lock_time) != 1 ) {
+ _pam_log(LOG_ERR,"bad number supplied; %s",*argv);
+ return PAM_AUTH_ERR;
+ }
+ }
+ else if ( ! strncmp( *argv, "unlock_time=", 12 ) ) {
+ log_phase_no_auth(phase, *argv);
+ if ( sscanf((*argv)+12,"%ld",&opts->unlock_time) != 1 ) {
+ _pam_log(LOG_ERR,"bad number supplied; %s",*argv);
+ return PAM_AUTH_ERR;
+ }
+ }
+ else if ( ! strcmp( *argv, "per_user" ) )
+ {
+ log_phase_no_auth(phase, *argv);
+ opts->ctrl |= OPT_PER_USER;
+ }
+ else if ( ! strcmp( *argv, "no_lock_time") )
+ {
+ log_phase_no_auth(phase, *argv);
+ opts->ctrl |= OPT_NO_LOCK_TIME;
+ }
+ else if ( ! strcmp( *argv, "no_reset" ) ) {
+ opts->ctrl |= OPT_NO_RESET;
+ }
+ else if ( ! strcmp ( *argv, "audit") ) {
+ opts->ctrl |= OPT_AUDIT;
+ }
+ else {
+ _pam_log(LOG_ERR, MODULE_NAME ": unknown option; %s",*argv);
+ }
+ }
+
+ return PAM_SUCCESS;
+}
+
+/*---------------------------------------------------------------------*/
+
/* --- Support function: get uid (and optionally username) from PAM or
cline_user --- */
@@ -107,9 +215,9 @@ static void _pam_log(int err, const char *format, ...)
static char *cline_user=0; /* cline_user is used in the administration prog */
#endif
-static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp )
+static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp, struct tally_options *opts)
{
- const char *user;
+ const char *user = NULL;
struct passwd *pw;
#ifdef MAIN
@@ -123,8 +231,10 @@ static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp )
return PAM_AUTH_ERR;
}
- if ( ! ( pw = getpwnam( user ) ) ) {
- _pam_log(LOG_ERR,MODULE_NAME ": pam_get_uid; no such user %s",user);
+ if ( ! ( pw = _pammodutil_getpwnam( pamh, user ) ) ) {
+ opts->ctrl & OPT_AUDIT ?
+ _pam_log(LOG_ERR,MODULE_NAME ": pam_get_uid; no such user %s",user) :
+ _pam_log(LOG_ERR,MODULE_NAME ": pam_get_uid; no such user");
return PAM_USER_UNKNOWN;
}
@@ -135,6 +245,42 @@ static int pam_get_uid( pam_handle_t *pamh, uid_t *uid, const char **userp )
/*---------------------------------------------------------------------*/
+/* --- Support functions: set/get tally data --- */
+
+static void _cleanup( pam_handle_t *pamh, void *data, int error_status )
+ {
+ free(data);
+ }
+
+static void tally_set_data( pam_handle_t *pamh, time_t oldtime )
+ {
+ time_t *data;
+
+ if ( (data=malloc(sizeof(time_t))) != NULL ) {
+ *data = oldtime;
+ pam_set_data(pamh, MODULE_NAME, (void *)data, _cleanup);
+ }
+ }
+
+static int tally_get_data( pam_handle_t *pamh, time_t *oldtime )
+ {
+ int rv;
+ const void *data;
+
+ rv = pam_get_data(pamh, MODULE_NAME, &data);
+ if ( rv == PAM_SUCCESS && oldtime != NULL ) {
+ *oldtime = *(const time_t *)data;
+ pam_set_data(pamh, MODULE_NAME, NULL, NULL);
+ }
+ else {
+ rv = -1;
+ *oldtime = 0;
+ }
+ return rv;
+ }
+
+/*---------------------------------------------------------------------*/
+
/* --- Support function: open/create tallyfile and return tally for uid --- */
/* If on entry *tally==TALLY_HI, tallyfile is opened READONLY */
@@ -189,7 +335,8 @@ static int get_tally( tally_t *tally,
if ( fseek( *TALLY, uid * sizeof(struct faillog), SEEK_SET ) ) {
_pam_log(LOG_ALERT, "fseek failed %s", filename);
- return PAM_AUTH_ERR;
+ fclose(*TALLY);
+ return PAM_AUTH_ERR;
}
if ( fileinfo.st_size <= uid * sizeof(struct faillog) ) {
@@ -253,82 +400,42 @@ static int set_tally( tally_t tally,
#define PAM_FUNCTION(name) \
PAM_EXTERN int name (pam_handle_t *pamh,int flags,int argc,const char **argv)
-#define RETURN_ERROR(i) return ((fail_on_error)?(i):(PAM_SUCCESS))
+#define RETURN_ERROR(i) return ((opts->ctrl & OPT_FAIL_ON_ERROR)?(i):(PAM_SUCCESS))
/*---------------------------------------------------------------------*/
/* --- tally bump function: bump tally for uid by (signed) inc --- */
-static int tally_bump (int inc,
+static int tally_bump (int inc, time_t *oldtime,
pam_handle_t *pamh,
- int flags,
- int argc,
- const char **argv) {
- uid_t uid;
-
- int
- fail_on_error = FALSE;
+ uid_t uid,
+ const char *user,
+ struct tally_options *opts) {
tally_t
tally = 0; /* !TALLY_HI --> Log opened for update */
- char
- no_magic_root = FALSE;
-
- char
- filename[ FILENAME_MAX ] = DEFAULT_LOGFILE;
-
- /* Should probably decode the parameters before anything else. */
-
- {
- for ( ; argc-- > 0; ++argv ) {
-
- /* generic options.. um, ignored. :] */
-
- if ( ! strcmp( *argv, "no_magic_root" ) ) {
- no_magic_root = TRUE;
- }
- else if ( ! strncmp( *argv, "file=", 5 ) ) {
- char const
- *from = (*argv)+5;
- char
- *to = filename;
- if ( *from!='/' || strlen(from)>FILENAME_MAX-1 ) {
- _pam_log(LOG_ERR,
- MODULE_NAME ": filename not /rooted or too long; ",
- *argv);
- RETURN_ERROR( PAM_AUTH_ERR );
- }
- while ( ( *to++ = *from++ ) );
- }
- else if ( ! strcmp( *argv, "onerr=fail" ) ) {
- fail_on_error=TRUE;
- }
- else if ( ! strcmp( *argv, "onerr=succeed" ) ) {
- fail_on_error=FALSE;
- }
- else {
- _pam_log(LOG_ERR, MODULE_NAME ": unknown option; %s",*argv);
- }
- } /* for() */
- }
-
- {
FILE
*TALLY = NULL;
const char
- *user = NULL,
*remote_host = NULL,
*cur_tty = NULL;
struct fail_s fs, *fsp = &fs;
+ int i;
- int i=pam_get_uid(pamh, &uid, &user);
- if ( i != PAM_SUCCESS ) RETURN_ERROR( i );
-
- i=get_tally( &tally, uid, filename, &TALLY, fsp );
+ i=get_tally( &tally, uid, opts->filename, &TALLY, fsp );
/* to remember old fail time (for locktime) */
fsp->fs_fail_time = fsp->fs_faillog.fail_time;
- fsp->fs_faillog.fail_time = time(NULL);
+ if ( inc > 0 ) {
+ if ( oldtime ) {
+ *oldtime = fsp->fs_faillog.fail_time;
+ }
+ fsp->fs_faillog.fail_time = time(NULL);
+ } else {
+ if ( oldtime ) {
+ fsp->fs_faillog.fail_time = *oldtime;
+ }
+ }
(void) pam_get_item(pamh, PAM_RHOST, (const void **)&remote_host);
if (!remote_host) {
@@ -350,7 +457,7 @@ static int tally_bump (int inc,
}
if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); }
- if ( no_magic_root || getuid() ) { /* no_magic_root kills uid test */
+ if ( !(opts->ctrl & OPT_MAGIC_ROOT) || getuid() ) { /* magic_root doesn't change tally */
tally+=inc;
@@ -361,213 +468,215 @@ static int tally_bump (int inc,
}
}
- i=set_tally( tally, uid, filename, &TALLY, fsp );
+ i=set_tally( tally, uid, opts->filename, &TALLY, fsp );
if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); }
- }
- return PAM_SUCCESS;
+ return PAM_SUCCESS;
}
-/*---------------------------------------------------------------------*/
-
-/* --- authentication management functions (only) --- */
-
-#ifdef PAM_SM_AUTH
-
-PAM_FUNCTION( pam_sm_authenticate ) {
- return tally_bump( 1, pamh, flags, argc, argv);
-}
-
-/* --- Seems to need this function. Ho hum. --- */
-
-PAM_FUNCTION( pam_sm_setcred ) { return PAM_SUCCESS; }
-
-#endif
-
-/*---------------------------------------------------------------------*/
-
-/* --- session management functions (only) --- */
-
-/*
- * Unavailable until .so files can be suid
- */
-
-#ifdef PAM_SM_SESSION
-
-/* To maintain a balance-tally of successful login/outs */
-
-PAM_FUNCTION( pam_sm_open_session ) {
- return tally_bump( 1, pamh, flags, argc, argv);
-}
-
-PAM_FUNCTION( pam_sm_close_session ) {
- return tally_bump(-1, pamh, flags, argc, argv);
-}
-
-#endif
-
-/*---------------------------------------------------------------------*/
-
-/* --- authentication management functions (only) --- */
-
-#ifdef PAM_SM_AUTH
-
-/* To lock out a user with an unacceptably high tally */
-
-PAM_FUNCTION( pam_sm_acct_mgmt ) {
- uid_t
- uid;
-
- int
- fail_on_error = FALSE;
+static int tally_check (time_t oldtime,
+ pam_handle_t *pamh,
+ uid_t uid,
+ const char *user,
+ struct tally_options *opts) {
tally_t
- deny = 0;
+ deny = opts->deny;
tally_t
tally = 0; /* !TALLY_HI --> Log opened for update */
+ long
+ lock_time = opts->lock_time;
- char
- no_magic_root = FALSE,
- even_deny_root_account = FALSE;
- char per_user = FALSE; /* if true then deny=.fail_max for user */
- char no_lock_time = FALSE; /* if true then don't use .fail_locktime */
-
- const char
- *user = NULL;
-
- enum TALLY_RESET
- reset = TALLY_RESET_DEFAULT;
-
- char
- filename[ FILENAME_MAX ] = DEFAULT_LOGFILE;
-
- /* Should probably decode the parameters before anything else. */
-
- {
- for ( ; argc-- > 0; ++argv ) {
-
- /* generic options.. um, ignored. :] */
-
- if ( ! strcmp( *argv, "no_magic_root" ) ) {
- no_magic_root = TRUE;
- }
- else if ( ! strcmp( *argv, "even_deny_root_account" ) ) {
- even_deny_root_account = TRUE;
- }
- else if ( ! strcmp( *argv, "reset" ) ) {
- reset = TALLY_RESET_RESET;
- }
- else if ( ! strcmp( *argv, "no_reset" ) ) {
- reset = TALLY_RESET_NO_RESET;
- }
- else if ( ! strncmp( *argv, "file=", 5 ) ) {
- char const
- *from = (*argv)+5;
- char
- *to = filename;
- if ( *from != '/' || strlen(from) > FILENAME_MAX-1 ) {
- _pam_log(LOG_ERR,
- MODULE_NAME ": filename not /rooted or too long; ",
- *argv);
- RETURN_ERROR( PAM_AUTH_ERR );
- }
- while ( ( *to++ = *from++ ) );
- }
- else if ( ! strncmp( *argv, "deny=", 5 ) ) {
- if ( sscanf((*argv)+5,TALLY_FMT,&deny) != 1 ) {
- _pam_log(LOG_ERR,"bad number supplied; %s",*argv);
- RETURN_ERROR( PAM_AUTH_ERR );
- }
- }
- else if ( ! strcmp( *argv, "onerr=fail" ) ) {
- fail_on_error=TRUE;
- }
- else if ( ! strcmp( *argv, "onerr=succeed" ) ) {
- fail_on_error=FALSE;
- }
- else if ( ! strcmp( *argv, "per_user" ) )
- {
- per_user = TRUE;
- }
- else if ( ! strcmp( *argv, "no_lock_time") )
- {
- no_lock_time = TRUE;
- }
- else {
- _pam_log(LOG_ERR, MODULE_NAME ": unknown option; %s",*argv);
- }
- } /* for() */
- }
-
- {
struct fail_s fs, *fsp = &fs;
FILE *TALLY=0;
- int i=pam_get_uid(pamh, &uid, &user);
- if ( i != PAM_SUCCESS ) RETURN_ERROR( i );
+ int i;
- i=get_tally( &tally, uid, filename, &TALLY, fsp );
- if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); }
+ i=get_tally( &tally, uid, opts->filename, &TALLY, fsp );
+ if (TALLY) fclose(TALLY);
+ if ( i != PAM_SUCCESS ) { RETURN_ERROR( i ); }
- if ( no_magic_root || getuid() ) { /* no_magic_root kills uid test */
+ if ( !(opts->ctrl & OPT_MAGIC_ROOT) || getuid() ) { /* magic_root skips tally check */
/* To deny or not to deny; that is the question */
/* if there's .fail_max entry and per_user=TRUE then deny=.fail_max */
- if ( (fsp->fs_faillog.fail_max) && (per_user) ) {
+ if ( (fsp->fs_faillog.fail_max) && (opts->ctrl & OPT_PER_USER) ) {
deny = fsp->fs_faillog.fail_max;
}
- if (fsp->fs_faillog.fail_locktime && fsp->fs_fail_time
- && (!no_lock_time) )
+ if ( (fsp->fs_faillog.fail_locktime) && (opts->ctrl & OPT_PER_USER) ) {
+ lock_time = fsp->fs_faillog.fail_locktime;
+ }
+ if (lock_time && oldtime
+ && !(opts->ctrl & OPT_NO_LOCK_TIME) )
{
- if ( (fsp->fs_faillog.fail_locktime + fsp->fs_fail_time) > time(NULL) )
+ if ( lock_time + oldtime > time(NULL) )
{
_pam_log(LOG_NOTICE,
"user %s ("UID_FMT") has time limit [%lds left]"
" since last failure.",
user,uid,
- fsp->fs_fail_time+fsp->fs_faillog.fail_locktime
+ oldtime+lock_time
-time(NULL));
return PAM_AUTH_ERR;
}
}
+ if (opts->unlock_time && oldtime)
+ {
+ if ( opts->unlock_time + oldtime <= time(NULL) )
+ { /* ignore deny check after unlock_time elapsed */
+ return PAM_SUCCESS;
+ }
+ }
if (
( deny != 0 ) && /* deny==0 means no deny */
( tally > deny ) && /* tally>deny means exceeded */
- ( even_deny_root_account || uid ) /* even_deny stops uid check */
+ ( ((opts->ctrl & OPT_DENY_ROOT) || uid) ) /* even_deny stops uid check */
) {
_pam_log(LOG_NOTICE,"user %s ("UID_FMT") tally "TALLY_FMT", deny "TALLY_FMT,
user, uid, tally, deny);
return PAM_AUTH_ERR; /* Only unconditional failure */
}
-
- /* resets for explicit reset
- * or by default if deny exists and not magic-root
- */
-
- if ( ( reset == TALLY_RESET_RESET ) ||
- ( reset == TALLY_RESET_DEFAULT && deny ) ) { tally=0; }
}
- else /* is magic root */ {
- /* Magic root skips deny test... */
+ return PAM_SUCCESS;
+}
+
+static int tally_reset (pam_handle_t *pamh,
+ uid_t uid,
+ const char *user,
+ struct tally_options *opts) {
+ tally_t
+ tally = 0; /* !TALLY_HI --> Log opened for update */
+
+ struct fail_s fs, *fsp = &fs;
+ FILE *TALLY=0;
+ int i;
+
+ i=get_tally( &tally, uid, opts->filename, &TALLY, fsp );
+ if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); }
+
+ /* resets if not magic root
+ */
- /* Magic root only resets on explicit reset, regardless of deny */
+ if ( (!(opts->ctrl & OPT_MAGIC_ROOT) || getuid())
+ && !(opts->ctrl & OPT_NO_RESET) )
+ { tally=0; }
- if ( reset == TALLY_RESET_RESET ) { tally=0; }
- }
if (tally == 0)
{
fsp->fs_faillog.fail_time = (time_t) 0;
strcpy(fsp->fs_faillog.fail_line, "");
}
- i=set_tally( tally, uid, filename, &TALLY, fsp );
+
+ i=set_tally( tally, uid, opts->filename, &TALLY, fsp );
if ( i != PAM_SUCCESS ) { if (TALLY) fclose(TALLY); RETURN_ERROR( i ); }
- }
- return PAM_SUCCESS;
+ return PAM_SUCCESS;
+}
+
+/*---------------------------------------------------------------------*/
+
+/* --- authentication management functions (only) --- */
+
+#ifdef PAM_SM_AUTH
+
+PAM_FUNCTION( pam_sm_authenticate ) {
+ int
+ rvcheck, rvbump;
+ time_t
+ oldtime = 0;
+ struct tally_options
+ options, *opts = &options;
+ uid_t
+ uid;
+ const char
+ *user;
+
+ rvcheck = tally_parse_args(opts, PHASE_AUTH, argc, argv);
+ if ( rvcheck != PAM_SUCCESS )
+ RETURN_ERROR( rvcheck );
+
+ rvcheck = pam_get_uid(pamh, &uid, &user, opts);
+ if ( rvcheck != PAM_SUCCESS )
+ RETURN_ERROR( rvcheck );
+
+ rvbump = tally_bump(1, &oldtime, pamh, uid, user, opts);
+ rvcheck = tally_check(oldtime, pamh, uid, user, opts);
+
+ tally_set_data(pamh, oldtime);
+
+ return rvcheck != PAM_SUCCESS ? rvcheck : rvbump;
+}
+
+PAM_FUNCTION( pam_sm_setcred ) {
+ int
+ rv;
+ time_t
+ oldtime = 0;
+ struct tally_options
+ options, *opts = &options;
+ uid_t
+ uid;
+ const char
+ *user;
+
+ rv = tally_parse_args(opts, PHASE_AUTH, argc, argv);
+ if ( rv != PAM_SUCCESS )
+ RETURN_ERROR( rv );
+
+ rv = pam_get_uid(pamh, &uid, &user, opts);
+ if ( rv != PAM_SUCCESS )
+ RETURN_ERROR( rv );
+
+ if ( tally_get_data(pamh, &oldtime) != 0 )
+ /* no data found */
+ return PAM_SUCCESS;
+
+ if ( (rv=tally_bump(-1, &oldtime, pamh, uid, user, opts)) != PAM_SUCCESS )
+ return rv;
+ return tally_reset(pamh, uid, user, opts);
+}
+
+#endif
+
+/*---------------------------------------------------------------------*/
+
+/* --- authentication management functions (only) --- */
+
+#ifdef PAM_SM_ACCOUNT
+
+/* To reset failcount of user on successfull login */
+
+PAM_FUNCTION( pam_sm_acct_mgmt ) {
+ int
+ rv;
+ time_t
+ oldtime = 0;
+ struct tally_options
+ options, *opts = &options;
+ uid_t
+ uid;
+ const char
+ *user;
+
+ rv = tally_parse_args(opts, PHASE_ACCOUNT, argc, argv);
+ if ( rv != PAM_SUCCESS )
+ RETURN_ERROR( rv );
+
+ rv = pam_get_uid(pamh, &uid, &user, opts);
+ if ( rv != PAM_SUCCESS )
+ RETURN_ERROR( rv );
+
+ if ( tally_get_data(pamh, &oldtime) != 0 )
+ /* no data found */
+ return PAM_SUCCESS;
+
+ if ( (rv=tally_bump(-1, &oldtime, pamh, uid, user, opts)) != PAM_SUCCESS )
+ return rv;
+ return tally_reset(pamh, uid, user, opts);
}
-#endif /* #ifdef PAM_SM_AUTH */
+#endif /* #ifdef PAM_SM_ACCOUNT */
/*-----------------------------------------------------------------------*/
@@ -589,18 +698,9 @@ struct pam_module _pam_tally_modstruct = {
#else
NULL,
#endif
-#ifdef PAM_SM_SESSION
- pam_sm_open_session,
- pam_sm_close_session,
-#else
NULL,
NULL,
-#endif
-#ifdef PAM_SM_PASSWORD
- pam_sm_chauthtok,
-#else
NULL,
-#endif
};
#endif /* #ifdef PAM_STATIC */
@@ -670,7 +770,12 @@ int main ( int argc, char **argv ) {
uid_t uid;
tally_t tally=cline_reset;
FILE *TALLY=0;
- int i=pam_get_uid( NULL, &uid, NULL);
+ struct tally_options opts;
+ int i;
+
+ memset(&opts, 0, sizeof(opts));
+ opts.ctrl = OPT_AUDIT;
+ i=pam_get_uid( NULL, &uid, NULL, &opts);
if ( i != PAM_SUCCESS ) {
fprintf(stderr,"%s: %s\n",*argv,pam_errors(i));
exit(0);
diff --git a/Linux-PAM/modules/pam_time/Makefile b/Linux-PAM/modules/pam_time/Makefile
index 647d3081..4aa4e276 100644
--- a/Linux-PAM/modules/pam_time/Makefile
+++ b/Linux-PAM/modules/pam_time/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:35 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:05 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_time/README b/Linux-PAM/modules/pam_time/README
index 4ef51531..0228b907 100644
--- a/Linux-PAM/modules/pam_time/README
+++ b/Linux-PAM/modules/pam_time/README
@@ -1,4 +1,4 @@
-$Id: README,v 1.1.1.1 2001/04/29 04:17:35 hartmans Exp $
+$Id: README,v 1.2 2000/12/04 19:02:35 baggins Exp $
This is a help file for the pam_time module. It explains the need for
pam_time and also the syntax of the /etc/security/time.conf file.
diff --git a/Linux-PAM/modules/pam_time/pam_time.c b/Linux-PAM/modules/pam_time/pam_time.c
index 5757a557..c04180f2 100644
--- a/Linux-PAM/modules/pam_time/pam_time.c
+++ b/Linux-PAM/modules/pam_time/pam_time.c
@@ -1,15 +1,15 @@
/* pam_time module */
/*
- * $Id: pam_time.c,v 1.1.1.2 2002/09/15 20:08:59 hartmans Exp $
+ * $Id: pam_time.c,v 1.5 2004/09/22 09:37:50 kukuk Exp $
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/6/22
* (File syntax and much other inspiration from the shadow package
* shadow-960129)
*/
-const static char rcsid[] =
-"$Id: pam_time.c,v 1.1.1.2 2002/09/15 20:08:59 hartmans Exp $;\n"
+static const char rcsid[] =
+"$Id: pam_time.c,v 1.5 2004/09/22 09:37:50 kukuk Exp $;\n"
"\t\tVersion 0.22 for Linux-PAM\n"
"Copyright (C) Andrew G. Morgan 1996 <morgan@linux.kernel.org>\n";
@@ -127,6 +127,7 @@ static int read_field(int fd, char **buf, int *from, int *to)
i = read(fd, *to + *buf, PAM_TIME_BUFLEN - *to);
if (i < 0) {
_log_err("error reading " PAM_TIME_CONF);
+ close(fd);
return -1;
} else if (!i) {
close(fd);
@@ -166,6 +167,7 @@ static int read_field(int fd, char **buf, int *from, int *to)
} else {
_log_err("internal error in " __FILE__
" at line %d", __LINE__ );
+ close(fd);
return -1;
}
break;
diff --git a/Linux-PAM/modules/pam_unix/CHANGELOG b/Linux-PAM/modules/pam_unix/CHANGELOG
index 206d30dd..509ce0a3 100644
--- a/Linux-PAM/modules/pam_unix/CHANGELOG
+++ b/Linux-PAM/modules/pam_unix/CHANGELOG
@@ -1,4 +1,4 @@
-$Id: CHANGELOG,v 1.1.1.1 2001/04/29 04:17:36 hartmans Exp $
+$Id: CHANGELOG,v 1.1.1.1 2000/06/20 22:12:01 agmorgan Exp $
* Mon Aug 16 1999 Jan Rêkorajski <baggins@pld.org.pl>
- fixed reentrancy problems
diff --git a/Linux-PAM/modules/pam_unix/Makefile b/Linux-PAM/modules/pam_unix/Makefile
index 03374512..7f32e073 100644
--- a/Linux-PAM/modules/pam_unix/Makefile
+++ b/Linux-PAM/modules/pam_unix/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:36 hartmans Exp $
+# $Id: Makefile,v 1.8 2004/11/08 08:58:37 kukuk Exp $
#
# This Makefile controls a build process of the pam_unix modules
# for Linux-PAM. You should not modify this Makefile.
@@ -18,6 +18,19 @@ include ../../Make.Rules
#USE_CRACKLIB=-D"USE_CRACKLIB"
#endif
+ifeq ($(shell if [ -f /usr/lib/cracklib_dict.hwm ]; then echo yes ; fi),yes)
+ CRACKLIB_DICTPATH=/usr/lib/cracklib_dict
+else
+ CRACKLIB_DICTPATH=/usr/share/dict/cracklib_dict
+endif
+EXTRAS += -DCRACKLIB_DICTS=\"$(CRACKLIB_DICTPATH)\"
+
+ifeq ($(HAVE_LIBCRYPT),yes)
+ EXTRALS += -lcrypt
+endif
+ifeq ($(HAVE_LIBNSL),yes)
+ EXTRALS += -lnsl
+endif
# do you want to use lckpwdf?
ifeq ($(WITH_LCKPWDF),yes)
USE_LCKPWDF=-D"USE_LCKPWDF"
@@ -37,12 +50,19 @@ endif
CHKPWD=unix_chkpwd
+BIGCRYPT=bigcrypt
+
EXTRAS += -DCHKPWD_HELPER=\"$(SUPLEMENTED)/$(CHKPWD)\"
+LINK_PAMMODUTILS = -L../pammodutil -lpammodutil
+INCLUDE_PAMMODUTILS = -I../pammodutil/include
+
########################################################################
-CFLAGS += $(USE_CRACKLIB) $(USE_LCKPWDF) $(NEED_LCKPWDF) $(EXTRAS)
-LDLIBS = $(EXTRALS)
+CFLAGS += $(USE_CRACKLIB) $(USE_LCKPWDF) $(NEED_LCKPWDF) $(EXTRAS) \
+ $(INCLUDE_PAMMODUTILS)
+
+LDLIBS = $(EXTRALS) $(LINK_PAMMODUTILS)
ifdef USE_CRACKLIB
CRACKLIB = -lcrack
@@ -69,7 +89,8 @@ endif
########################### don't edit below #######################
-all: dirs info $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) register
+all: dirs info $(PLUS) $(LIBSHARED) $(LIBSTATIC) $(CHKPWD) $(BIGCRYPT) \
+ register
dynamic/%.o : %.c
$(CC) $(CFLAGS) $(DYNAMIC) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
@@ -107,7 +128,7 @@ ifdef DYNAMIC
$(LIBOBJD): $(LIBSRC)
$(LIBSHARED): $(LIBOBJD)
- $(LD_D) -o $@ $(LIBOBJD) $(PLUS) $(CRACKLIB) $(LDLIBS) $(LIBNSL) $(LIBCRYPT)
+ $(LD_D) -o $@ $(LIBOBJD) $(PLUS) $(CRACKLIB) $(LDLIBS) $(LIBNSL) $(LIBCRYPT) $(NEED_LINK_LIB_C) -L../../libpam -lpam
endif
ifdef STATIC
@@ -120,7 +141,10 @@ endif
$(CHKPWD): unix_chkpwd.o md5_good.o md5_broken.o \
md5_crypt_good.o md5_crypt_broken.o \
bigcrypt.o
- $(CC) -o $(CHKPWD) $^ $(LDLIBS) $(LIBCRYPT)
+ $(CC) $(CFLAGS) -o $(CHKPWD) $^ $(LDLIBS) $(LIBCRYPT)
+
+$(BIGCRYPT): bigcrypt_main.o bigcrypt.o
+ $(CC) -o $(BIGCRYPT) $^ $(LDLIBS) $(LIBCRYPT)
unix_chkpwd.o: unix_chkpwd.c
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
@@ -158,7 +182,7 @@ remove:
rm -f $(FAKEROOT)$(SUPLEMENTED)/$(CHKPWD)
clean:
- rm -f $(LIBOBJD) $(LIBOBJS) $(CHKPWD) *.o *.so core
+ rm -f $(LIBOBJD) $(LIBOBJS) $(CHKPWD) $(BIGCRYPT) *.o *.so core
rm -f *~ *.a *.out *.bak
rm -rf dynamic static
diff --git a/Linux-PAM/modules/pam_unix/README b/Linux-PAM/modules/pam_unix/README
index d6b1f395..afeee3da 100644
--- a/Linux-PAM/modules/pam_unix/README
+++ b/Linux-PAM/modules/pam_unix/README
@@ -31,5 +31,7 @@ The following options are recognized:
nis - use NIS RPC for setting new password
remember=X - remember X old passwords, they are kept in
/etc/security/opasswd in MD5 crypted form
+ broken_shadow - ignore errors reading shadow information for
+ users in the account management module
invalid arguments are logged to syslog.
diff --git a/Linux-PAM/modules/pam_unix/bigcrypt_main.c b/Linux-PAM/modules/pam_unix/bigcrypt_main.c
new file mode 100644
index 00000000..70819072
--- /dev/null
+++ b/Linux-PAM/modules/pam_unix/bigcrypt_main.c
@@ -0,0 +1,18 @@
+#include <stdio.h>
+#include <string.h>
+
+extern const char *bigcrypt(const char *password, const char *salt);
+
+int
+main(int argc, char **argv)
+{
+ if (argc < 3) {
+ fprintf(stderr, "Usage: %s password salt\n",
+ strchr(argv[0], '/') ?
+ (strchr(argv[0], '/') + 1) :
+ argv[0]);
+ return 0;
+ }
+ fprintf(stdout, "%s\n", bigcrypt(argv[1], argv[2]));
+ return 0;
+}
diff --git a/Linux-PAM/modules/pam_unix/md5.c b/Linux-PAM/modules/pam_unix/md5.c
index 3fb50137..7ee9ed00 100644
--- a/Linux-PAM/modules/pam_unix/md5.c
+++ b/Linux-PAM/modules/pam_unix/md5.c
@@ -1,5 +1,5 @@
/*
- * $Id: md5.c,v 1.1.1.1 2001/04/29 04:17:37 hartmans Exp $
+ * $Id: md5.c,v 1.1.1.1 2000/06/20 22:12:03 agmorgan Exp $
*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
diff --git a/Linux-PAM/modules/pam_unix/md5_crypt.c b/Linux-PAM/modules/pam_unix/md5_crypt.c
index 8ae84588..8b7bc66b 100644
--- a/Linux-PAM/modules/pam_unix/md5_crypt.c
+++ b/Linux-PAM/modules/pam_unix/md5_crypt.c
@@ -1,5 +1,5 @@
/*
- * $Id: md5_crypt.c,v 1.1.1.2 2002/09/15 20:09:01 hartmans Exp $
+ * $Id: md5_crypt.c,v 1.2 2001/07/10 20:24:16 vorlon Exp $
*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
diff --git a/Linux-PAM/modules/pam_unix/pam_unix_acct.c b/Linux-PAM/modules/pam_unix/pam_unix_acct.c
index 178b6037..02e07ba6 100644
--- a/Linux-PAM/modules/pam_unix/pam_unix_acct.c
+++ b/Linux-PAM/modules/pam_unix/pam_unix_acct.c
@@ -53,6 +53,7 @@
#define PAM_SM_ACCOUNT
#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
#ifndef LINUX_PAM
#include <security/pam_appl.h>
@@ -89,7 +90,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags,
return PAM_USER_UNKNOWN;
}
- pwent = getpwnam(uname);
+ pwent = _pammodutil_getpwnam(pamh, uname);
if (!pwent) {
_log_err(LOG_ALERT, pamh
,"could not identify user (from getpwnam(%s))"
@@ -113,7 +114,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags,
return PAM_CRED_INSUFFICIENT;
}
}
- spent = getspnam( uname );
+ spent = _pammodutil_getspnam (pamh, uname);
if (save_uid == pwent->pw_uid)
setreuid( save_uid, save_euid );
else {
@@ -122,19 +123,21 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags,
setreuid( -1, save_euid );
}
- } else if (!strcmp( pwent->pw_passwd, "x" )) {
- spent = getspnam(uname);
- } else {
+ } else if (_unix_shadowed (pwent))
+ spent = _pammodutil_getspnam (pamh, uname);
+ else
return PAM_SUCCESS;
- }
+
+ if (!spent)
+ if (on(UNIX_BROKEN_SHADOW,ctrl))
+ return PAM_SUCCESS;
if (!spent)
return PAM_AUTHINFO_UNAVAIL; /* Couldn't get username from shadow */
curdays = time(NULL) / (60 * 60 * 24);
D(("today is %d, last change %d", curdays, spent->sp_lstchg));
- if ((curdays > spent->sp_expire) && (spent->sp_expire != -1)
- && (spent->sp_lstchg != 0)) {
+ if ((curdays > spent->sp_expire) && (spent->sp_expire != -1)) {
_log_err(LOG_NOTICE, pamh
,"account %s has expired (account expired)"
,uname);
@@ -143,18 +146,6 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags,
D(("account expired"));
return PAM_ACCT_EXPIRED;
}
- if ((curdays > (spent->sp_lstchg + spent->sp_max + spent->sp_inact))
- && (spent->sp_max != -1) && (spent->sp_inact != -1)
- && (spent->sp_lstchg != 0)) {
- _log_err(LOG_NOTICE, pamh
- ,"account %s has expired (failed to change password)"
- ,uname);
- _make_remark(pamh, ctrl, PAM_ERROR_MSG,
- "Your account has expired; please contact your system administrator");
- D(("account expired 2"));
- return PAM_ACCT_EXPIRED;
- }
- D(("when was the last change"));
if (spent->sp_lstchg == 0) {
_log_err(LOG_NOTICE, pamh
,"expired password for user %s (root enforced)"
@@ -164,7 +155,25 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags,
D(("need a new password"));
return PAM_NEW_AUTHTOK_REQD;
}
- if (((spent->sp_lstchg + spent->sp_max) < curdays) && (spent->sp_max != -1)) {
+ if (curdays < spent->sp_lstchg) {
+ _log_err(LOG_DEBUG, pamh
+ ,"account %s has password changed in future"
+ ,uname);
+ return PAM_SUCCESS;
+ }
+ if ((curdays - spent->sp_lstchg > spent->sp_max)
+ && (curdays - spent->sp_lstchg > spent->sp_inact)
+ && (curdays - spent->sp_lstchg > spent->sp_max + spent->sp_inact)
+ && (spent->sp_max != -1) && (spent->sp_inact != -1)) {
+ _log_err(LOG_NOTICE, pamh
+ ,"account %s has expired (failed to change password)"
+ ,uname);
+ _make_remark(pamh, ctrl, PAM_ERROR_MSG,
+ "Your account has expired; please contact your system administrator");
+ D(("account expired 2"));
+ return PAM_ACCT_EXPIRED;
+ }
+ if ((curdays - spent->sp_lstchg > spent->sp_max) && (spent->sp_max != -1)) {
_log_err(LOG_DEBUG, pamh
,"expired password for user %s (password aged)"
,uname);
@@ -173,7 +182,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t * pamh, int flags,
D(("need a new password 2"));
return PAM_NEW_AUTHTOK_REQD;
}
- if ((curdays > (spent->sp_lstchg + spent->sp_max - spent->sp_warn))
+ if ((curdays - spent->sp_lstchg > spent->sp_max - spent->sp_warn)
&& (spent->sp_max != -1) && (spent->sp_warn != -1)) {
daysleft = (spent->sp_lstchg + spent->sp_max) - curdays;
_log_err(LOG_DEBUG, pamh
diff --git a/Linux-PAM/modules/pam_unix/pam_unix_auth.c b/Linux-PAM/modules/pam_unix/pam_unix_auth.c
index 67497e06..39e0cde5 100644
--- a/Linux-PAM/modules/pam_unix/pam_unix_auth.c
+++ b/Linux-PAM/modules/pam_unix/pam_unix_auth.c
@@ -15,13 +15,13 @@
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
- *
+ *
* ALTERNATIVELY, this product may be distributed under the terms of
* the GNU Public License, in which case the provisions of the GPL are
* required INSTEAD OF the above restrictions. (This clause is
* necessary due to a potential bad interaction between the GPL and
* the restrictions contained in a BSD-style copyright.)
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@@ -88,7 +88,8 @@ do { \
*ret_data = retval; \
pam_set_data(pamh, "unix_setcred_return", \
(void *) ret_data, setcred_free); \
- } \
+ } else if (ret_data) \
+ free (ret_data); \
D(("done. [%s]", pam_strerror(pamh, retval))); \
return retval; \
} while (0)
@@ -148,7 +149,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags
/* if this user does not have a password... */
- if (_unix_blankpasswd(ctrl, name)) {
+ if (_unix_blankpasswd(pamh, ctrl, name)) {
D(("user '%s' has blank passwd", name));
name = NULL;
retval = PAM_SUCCESS;
@@ -183,7 +184,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags
}
-/*
+/*
* The only thing _pam_set_credentials_unix() does is initialization of
* UNIX group IDs.
*
@@ -203,7 +204,7 @@ PAM_EXTERN int pam_sm_setcred(pam_handle_t * pamh, int flags
retval = PAM_SUCCESS;
D(("recovering return code from auth call"));
- /* We will only find something here if UNIX_LIKE_AUTH is set --
+ /* We will only find something here if UNIX_LIKE_AUTH is set --
don't worry about an explicit check of argv. */
pam_get_data(pamh, "unix_setcred_return", (const void **) &pretval);
if(pretval) {
diff --git a/Linux-PAM/modules/pam_unix/pam_unix_passwd.c b/Linux-PAM/modules/pam_unix/pam_unix_passwd.c
index 6b51a6b2..2ea57cc6 100644
--- a/Linux-PAM/modules/pam_unix/pam_unix_passwd.c
+++ b/Linux-PAM/modules/pam_unix/pam_unix_passwd.c
@@ -1,5 +1,5 @@
/*
- * Main coding by Elliot Lee <sopwith@redhat.com>, Red Hat Software.
+ * Main coding by Elliot Lee <sopwith@redhat.com>, Red Hat Software.
* Copyright (C) 1996.
* Copyright (c) Jan Rêkorajski, 1999.
*
@@ -73,6 +73,8 @@
#include <security/pam_appl.h>
#endif /* LINUX_PAM */
+#include <security/_pam_modutil.h>
+
#include "yppasswd.h"
#include "md5.h"
#include "support.h"
@@ -88,7 +90,7 @@ extern int getrpcport(const char *host, unsigned long prognum,
*/
#ifdef NEED_LCKPWDF
-#include "./lckpwdf.-c"
+# include "./lckpwdf.-c"
#endif
extern char *bigcrypt(const char *key, const char *salt);
@@ -114,7 +116,9 @@ extern char *bigcrypt(const char *key, const char *salt);
#define MAX_PASSWD_TRIES 3
#define PW_TMPFILE "/etc/npasswd"
#define SH_TMPFILE "/etc/nshadow"
+#ifndef CRACKLIB_DICTS
#define CRACKLIB_DICTS "/usr/share/dict/cracklib_dict"
+#endif
#define OPW_TMPFILE "/etc/security/nopasswd"
#define OLD_PASSWORDS_FILE "/etc/security/opasswd"
@@ -215,7 +219,7 @@ static int check_old_password(const char *forwho, const char *newpass)
opwfile = fopen(OLD_PASSWORDS_FILE, "r");
if (opwfile == NULL)
- return PAM_AUTHTOK_ERR;
+ return PAM_ABORT;
while (fgets(buf, 16380, opwfile)) {
if (!strncmp(buf, forwho, strlen(forwho))) {
@@ -242,7 +246,8 @@ static int check_old_password(const char *forwho, const char *newpass)
return retval;
}
-static int save_old_password(const char *forwho, const char *oldpass,
+static int save_old_password(pam_handle_t *pamh,
+ const char *forwho, const char *oldpass,
int howmany)
{
static char buf[16384];
@@ -254,6 +259,7 @@ static int save_old_password(const char *forwho, const char *oldpass,
int oldmask;
int found = 0;
struct passwd *pwd = NULL;
+ struct stat st;
if (howmany < 0) {
return PAM_SUCCESS;
@@ -276,8 +282,25 @@ static int save_old_password(const char *forwho, const char *oldpass,
return PAM_AUTHTOK_ERR;
}
- chown(OPW_TMPFILE, 0, 0);
- chmod(OPW_TMPFILE, 0600);
+ if (fstat (fileno (opwfile), &st) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ return PAM_AUTHTOK_ERR;
+ }
+
+ if (fchown (fileno (pwfile), st.st_uid, st.st_gid) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ return PAM_AUTHTOK_ERR;
+ }
+ if (fchmod (fileno (pwfile), st.st_mode) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ return PAM_AUTHTOK_ERR;
+ }
while (fgets(buf, 16380, opwfile)) {
if (!strncmp(buf, forwho, strlen(forwho))) {
@@ -314,7 +337,7 @@ static int save_old_password(const char *forwho, const char *oldpass,
fclose(opwfile);
if (!found) {
- pwd = getpwnam(forwho);
+ pwd = _pammodutil_getpwnam(pamh, forwho);
if (pwd == NULL) {
err = 1;
} else {
@@ -335,18 +358,20 @@ static int save_old_password(const char *forwho, const char *oldpass,
}
if (!err) {
- rename(OPW_TMPFILE, OLD_PASSWORDS_FILE);
- return PAM_SUCCESS;
- } else {
- unlink(OPW_TMPFILE);
- return PAM_AUTHTOK_ERR;
+ if (!rename(OPW_TMPFILE, OLD_PASSWORDS_FILE)) {
+ return PAM_SUCCESS;
+ }
}
+
+ unlink(OPW_TMPFILE);
+ return PAM_AUTHTOK_ERR;
}
static int _update_passwd(pam_handle_t *pamh,
const char *forwho, const char *towhat)
{
struct passwd *tmpent = NULL;
+ struct stat st;
FILE *pwfile, *opwfile;
int err = 1;
int oldmask;
@@ -364,9 +389,26 @@ static int _update_passwd(pam_handle_t *pamh,
return PAM_AUTHTOK_ERR;
}
- chown(PW_TMPFILE, 0, 0);
- chmod(PW_TMPFILE, 0644);
- tmpent = fgetpwent(opwfile);
+ if (fstat (fileno (opwfile), &st) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ return PAM_AUTHTOK_ERR;
+ }
+
+ if (fchown (fileno (pwfile), st.st_uid, st.st_gid) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ return PAM_AUTHTOK_ERR;
+ }
+ if (fchmod (fileno (pwfile), st.st_mode) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ }
+
+ tmpent = fgetpwent (opwfile);
while (tmpent) {
if (!strcmp(tmpent->pw_name, forwho)) {
/* To shut gcc up */
@@ -375,7 +417,7 @@ static int _update_passwd(pam_handle_t *pamh,
char *charp;
} assigned_passwd;
assigned_passwd.const_charp = towhat;
-
+
tmpent->pw_passwd = assigned_passwd.charp;
err = 0;
}
@@ -394,18 +436,20 @@ static int _update_passwd(pam_handle_t *pamh,
}
if (!err) {
- rename(PW_TMPFILE, "/etc/passwd");
- _log_err(LOG_NOTICE, pamh, "password changed for %s", forwho);
- return PAM_SUCCESS;
- } else {
- unlink(PW_TMPFILE);
- return PAM_AUTHTOK_ERR;
+ if (!rename(PW_TMPFILE, "/etc/passwd")) {
+ _log_err(LOG_NOTICE, pamh, "password changed for %s", forwho);
+ return PAM_SUCCESS;
+ }
}
+
+ unlink(PW_TMPFILE);
+ return PAM_AUTHTOK_ERR;
}
-static int _update_shadow(const char *forwho, char *towhat)
+static int _update_shadow(pam_handle_t *pamh, const char *forwho, char *towhat)
{
struct spwd *spwdent = NULL, *stmpent = NULL;
+ struct stat st;
FILE *pwfile, *opwfile;
int err = 1;
int oldmask;
@@ -427,8 +471,26 @@ static int _update_shadow(const char *forwho, char *towhat)
return PAM_AUTHTOK_ERR;
}
- chown(SH_TMPFILE, 0, 0);
- chmod(SH_TMPFILE, 0600);
+ if (fstat (fileno (opwfile), &st) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ return PAM_AUTHTOK_ERR;
+ }
+
+ if (fchown (fileno (pwfile), st.st_uid, st.st_gid) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ return PAM_AUTHTOK_ERR;
+ }
+ if (fchmod (fileno (pwfile), st.st_mode) == -1)
+ {
+ fclose (opwfile);
+ fclose (pwfile);
+ return PAM_AUTHTOK_ERR;
+ }
+
stmpent = fgetspent(opwfile);
while (stmpent) {
@@ -455,12 +517,14 @@ static int _update_shadow(const char *forwho, char *towhat)
}
if (!err) {
- rename(SH_TMPFILE, "/etc/shadow");
- return PAM_SUCCESS;
- } else {
- unlink(SH_TMPFILE);
- return PAM_AUTHTOK_ERR;
+ if (!rename(SH_TMPFILE, "/etc/shadow")) {
+ _log_err(LOG_NOTICE, pamh, "password changed for %s", forwho);
+ return PAM_SUCCESS;
+ }
}
+
+ unlink(SH_TMPFILE);
+ return PAM_AUTHTOK_ERR;
}
static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
@@ -471,14 +535,28 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
D(("called"));
- setpwent();
pwd = getpwnam(forwho);
- endpwent();
- if (pwd == NULL)
- return PAM_AUTHTOK_ERR;
+ if (pwd == NULL) {
+ retval = PAM_AUTHTOK_ERR;
+ goto done;
+ }
- if (on(UNIX_NIS, ctrl)) {
+ if (_unix_comesfromsource(pamh, forwho, 1, 0)) {
+ /* first, save old password */
+ if (save_old_password(pamh, forwho, fromwhat, remember)) {
+ retval = PAM_AUTHTOK_ERR;
+ goto done;
+ }
+ if (on(UNIX_SHADOW, ctrl) || _unix_shadowed(pwd)) {
+ retval = _update_shadow(pamh, forwho, towhat);
+ if (retval == PAM_SUCCESS)
+ if (!_unix_shadowed(pwd))
+ retval = _update_passwd(pamh, forwho, "x");
+ } else {
+ retval = _update_passwd(pamh, forwho, towhat);
+ }
+ } else if (on(UNIX_NIS, ctrl) && _unix_comesfromsource(pamh, forwho, 0, 1)) {
struct timeval timeout;
struct yppasswd yppwd;
CLIENT *clnt;
@@ -486,6 +564,10 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
int status;
int err = 0;
+ /* Unlock passwd file to avoid deadlock */
+#ifdef USE_LCKPWDF
+ ulckpwdf();
+#endif
/* Make RPC call to NIS server */
if ((master = getNISserver(pamh)) == NULL)
return PAM_TRY_AGAIN;
@@ -498,7 +580,7 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
yppwd.newpw.pw_gecos = pwd->pw_gecos;
yppwd.newpw.pw_dir = pwd->pw_dir;
yppwd.newpw.pw_shell = pwd->pw_shell;
- yppwd.oldpass = fromwhat;
+ yppwd.oldpass = fromwhat ? fromwhat : "";
yppwd.newpw.pw_passwd = towhat;
D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho));
@@ -540,17 +622,11 @@ static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
#endif
return retval;
}
- /* first, save old password */
- if (save_old_password(forwho, fromwhat, remember)) {
- return PAM_AUTHTOK_ERR;
- }
- if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) {
- retval = _update_shadow(forwho, towhat);
- if (retval == PAM_SUCCESS)
- retval = _update_passwd(pamh, forwho, "x");
- } else {
- retval = _update_passwd(pamh, forwho, towhat);
- }
+
+done:
+#ifdef USE_LCKPWDF
+ ulckpwdf();
+#endif
return retval;
}
@@ -563,13 +639,11 @@ static int _unix_verify_shadow(const char *user, unsigned int ctrl)
int retval = PAM_SUCCESS;
/* UNIX passwords area */
- setpwent();
pwd = getpwnam(user); /* Get password file entry... */
- endpwent();
if (pwd == NULL)
return PAM_AUTHINFO_UNAVAIL; /* We don't need to do the rest... */
- if (strcmp(pwd->pw_passwd, "x") == 0) {
+ if (_unix_shadowed(pwd)) {
/* ...and shadow password file entry for this user, if shadowing
is enabled */
setspent();
@@ -579,7 +653,7 @@ static int _unix_verify_shadow(const char *user, unsigned int ctrl)
if (spwdent == NULL)
return PAM_AUTHINFO_UNAVAIL;
} else {
- if (strcmp(pwd->pw_passwd,"*NP*") == 0) { /* NIS+ */
+ if (strcmp(pwd->pw_passwd,"*NP*") == 0) { /* NIS+ */
uid_t save_uid;
save_uid = geteuid();
@@ -661,11 +735,17 @@ static int _pam_unix_approve_pass(pam_handle_t * pamh
#else
if (strlen(pass_new) < 6)
remark = "You must choose a longer password";
- D(("lenth check [%s]", remark));
+ D(("length check [%s]", remark));
#endif
- if (on(UNIX_REMEMBER_PASSWD, ctrl))
- if ((retval = check_old_password(user, pass_new)) != PAM_SUCCESS)
+ if (on(UNIX_REMEMBER_PASSWD, ctrl)) {
+ if ((retval = check_old_password(user, pass_new)) == PAM_AUTHTOK_ERR)
remark = "Password has been already used. Choose another.";
+ if (retval == PAM_ABORT) {
+ _log_err(LOG_ERR, pamh, "can't open %s file to check old passwords",
+ OLD_PASSWORDS_FILE);
+ return retval;
+ }
+ }
}
if (remark) {
_make_remark(pamh, ctrl, PAM_ERROR_MSG, remark);
@@ -689,33 +769,12 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
D(("called."));
-#ifdef USE_LCKPWDF
- /* our current locking system requires that we lock the
- entire password database. This avoids both livelock
- and deadlock. */
- /* These values for the number of attempts and the sleep time
- are, of course, completely arbitrary.
- My reading of the PAM docs is that, once pam_chauthtok() has been
- called with PAM_UPDATE_AUTHTOK, we are obliged to take any
- reasonable steps to make sure the token is updated; so retrying
- for 1/10 sec. isn't overdoing it.
- The other possibility is to call lckpwdf() on the first
- pam_chauthtok() pass, and hold the lock until released in the
- second pass--but is this guaranteed to work? -SRL */
- i=0;
- while((retval = lckpwdf()) != 0 && i < 100) {
- usleep(1000);
- }
- if(retval != 0) {
- return PAM_AUTHTOK_LOCK_BUSY;
- }
-#endif
ctrl = _set_ctrl(pamh, flags, &remember, argc, argv);
/*
* First get the name of a user
*/
- retval = pam_get_user(pamh, &user, "Username: ");
+ retval = pam_get_user(pamh, &user, NULL);
if (retval == PAM_SUCCESS) {
/*
* Various libraries at various times have had bugs related to
@@ -725,9 +784,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
*/
if (user == NULL || !isalnum(*user)) {
_log_err(LOG_ERR, pamh, "bad username [%s]", user);
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
return PAM_USER_UNKNOWN;
}
if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
@@ -737,15 +793,42 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
if (on(UNIX_DEBUG, ctrl))
_log_err(LOG_DEBUG, pamh,
"password - could not identify user");
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
return retval;
}
D(("Got username of %s", user));
/*
+ * Before we do anything else, check to make sure that the user's
+ * info is in one of the databases we can modify from this module,
+ * which currently is 'files' and 'nis'. We have to do this because
+ * getpwnam() doesn't tell you *where* the information it gives you
+ * came from, nor should it. That's our job.
+ */
+ if (_unix_comesfromsource(pamh, user, 1, 1) == 0) {
+ _log_err(LOG_DEBUG, pamh,
+ "user \"%s\" does not exist in /etc/passwd or NIS",
+ user);
+ return PAM_USER_UNKNOWN;
+ } else {
+ struct passwd *pwd;
+ _unix_getpwnam(pamh, user, 1, 1, &pwd);
+ if (pwd == NULL) {
+ _log_err(LOG_DEBUG, pamh,
+ "user \"%s\" has corrupted passwd entry",
+ user);
+ return PAM_USER_UNKNOWN;
+ }
+ if (!_unix_shadowed(pwd) &&
+ (strchr(pwd->pw_passwd, '*') != NULL)) {
+ _log_err(LOG_DEBUG, pamh,
+ "user \"%s\" does not have modifiable password",
+ user);
+ return PAM_USER_UNKNOWN;
+ }
+ }
+
+ /*
* This is not an AUTH module!
*/
if (on(UNIX__NONULL, ctrl))
@@ -760,10 +843,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
D(("prelim check"));
- if (_unix_blankpasswd(ctrl, user)) {
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
+ if (_unix_blankpasswd(pamh, ctrl, user)) {
return PAM_SUCCESS;
} else if (off(UNIX__IAMROOT, ctrl)) {
@@ -773,9 +853,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
if (Announce == NULL) {
_log_err(LOG_CRIT, pamh,
"password - out of memory");
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
return PAM_BUF_ERR;
}
(void) strcpy(Announce, greeting);
@@ -795,9 +872,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
if (retval != PAM_SUCCESS) {
_log_err(LOG_NOTICE, pamh
,"password - (old) token not obtained");
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
return retval;
}
/* verify that this is the password for this user */
@@ -812,9 +886,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
if (retval != PAM_SUCCESS) {
D(("Authentication failed"));
pass_old = NULL;
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
return retval;
}
retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
@@ -867,19 +938,9 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
if (retval != PAM_SUCCESS) {
_log_err(LOG_NOTICE, pamh, "user not authenticated");
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
- return retval;
- }
- retval = _unix_verify_shadow(user, ctrl);
- if (retval != PAM_SUCCESS) {
- _log_err(LOG_NOTICE, pamh, "user not authenticated 2");
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
return retval;
}
+
D(("get new password now"));
lctrl = ctrl;
@@ -908,9 +969,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
,"password - new password not obtained");
}
pass_old = NULL; /* tidy up */
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
return retval;
}
D(("returned to _unix_chauthtok"));
@@ -931,11 +989,56 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
_log_err(LOG_NOTICE, pamh,
"new password not acceptable");
pass_new = pass_old = NULL; /* tidy up */
+ return retval;
+ }
+#ifdef USE_LCKPWDF
+ /* These values for the number of attempts and the sleep time
+ are, of course, completely arbitrary.
+ My reading of the PAM docs is that, once pam_chauthtok() has been
+ called with PAM_UPDATE_AUTHTOK, we are obliged to take any
+ reasonable steps to make sure the token is updated; so retrying
+ for 1/10 sec. isn't overdoing it. */
+ i=0;
+ while((retval = lckpwdf()) != 0 && i < 100) {
+ usleep(1000);
+ i++;
+ }
+ if(retval != 0) {
+ return PAM_AUTHTOK_LOCK_BUSY;
+ }
+#endif
+
+ if (pass_old) {
+ retval = _unix_verify_password(pamh, user, pass_old, ctrl);
+ if (retval != PAM_SUCCESS) {
+ _log_err(LOG_NOTICE, pamh, "user password changed by another process");
+#ifdef USE_LCKPWDF
+ ulckpwdf();
+#endif
+ return retval;
+ }
+ }
+
+ retval = _unix_verify_shadow(user, ctrl);
+ if (retval != PAM_SUCCESS) {
+ _log_err(LOG_NOTICE, pamh, "user not authenticated 2");
#ifdef USE_LCKPWDF
ulckpwdf();
#endif
return retval;
}
+
+ retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
+ if (retval != PAM_SUCCESS) {
+ _log_err(LOG_NOTICE, pamh,
+ "new password not acceptable 2");
+ pass_new = pass_old = NULL; /* tidy up */
+#ifdef USE_LCKPWDF
+ ulckpwdf();
+#endif
+ return retval;
+ }
+
/*
* By reaching here we have approved the passwords and must now
* rebuild the password database file.
@@ -962,7 +1065,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
salt[2] = '\0';
if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) {
- /*
+ /*
* to avoid using the _extensions_ of the bigcrypt()
* function we truncate the newly entered password
* [Problems that followed from this are fixed as per
@@ -998,6 +1101,8 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
retval = _do_setpass(pamh, user, pass_old, tpass, ctrl,
remember);
+ /* _do_setpass has called ulckpwdf for us */
+
_pam_delete(tpass);
pass_old = pass_new = NULL;
} else { /* something has broken with the module */
@@ -1008,9 +1113,6 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
D(("retval was %d", retval));
-#ifdef USE_LCKPWDF
- ulckpwdf();
-#endif
return retval;
}
@@ -1027,4 +1129,3 @@ struct pam_module _pam_unix_passwd_modstruct = {
pam_sm_chauthtok,
};
#endif
-
diff --git a/Linux-PAM/modules/pam_unix/pam_unix_sess.c b/Linux-PAM/modules/pam_unix/pam_unix_sess.c
index 0784bff8..a29a7085 100644
--- a/Linux-PAM/modules/pam_unix/pam_unix_sess.c
+++ b/Linux-PAM/modules/pam_unix/pam_unix_sess.c
@@ -1,5 +1,5 @@
/*
- * $Id: pam_unix_sess.c,v 1.1.1.1 2001/04/29 04:17:39 hartmans Exp $
+ * $Id: pam_unix_sess.c,v 1.5 2005/03/23 14:35:21 t8m Exp $
*
* Copyright Alexander O. Yuriev, 1996. All rights reserved.
* Copyright Jan Rêkorajski, 1999. All rights reserved.
@@ -53,6 +53,7 @@
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
#ifndef LINUX_PAM
#include <security/pam_appl.h>
@@ -71,27 +72,31 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t * pamh, int flags,
char *user_name, *service;
unsigned int ctrl;
int retval;
+ const char *login_name;
D(("called."));
ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
- if (user_name == NULL || retval != PAM_SUCCESS) {
+ if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
_log_err(LOG_CRIT, pamh,
"open_session - error recovering username");
return PAM_SESSION_ERR; /* How did we get authenticated with
no username?! */
}
retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service);
- if (service == NULL || retval != PAM_SUCCESS) {
+ if (service == NULL || *service == '\0' || retval != PAM_SUCCESS) {
_log_err(LOG_CRIT, pamh,
"open_session - error recovering service");
return PAM_SESSION_ERR;
}
- _log_err(LOG_INFO, pamh, "session opened for user %s by %s(uid=%d)"
- ,user_name
- ,PAM_getlogin() == NULL ? "" : PAM_getlogin(), getuid());
+ login_name = _pammodutil_getlogin(pamh);
+ if (login_name == NULL) {
+ login_name = "";
+ }
+ _log_err(LOG_INFO, pamh, "session opened for user %s by %s(uid=%d)",
+ user_name, login_name, getuid());
return PAM_SUCCESS;
}
@@ -108,14 +113,14 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t * pamh, int flags,
ctrl = _set_ctrl(pamh, flags, NULL, argc, argv);
retval = pam_get_item(pamh, PAM_USER, (void *) &user_name);
- if (user_name == NULL || retval != PAM_SUCCESS) {
+ if (user_name == NULL || *user_name == '\0' || retval != PAM_SUCCESS) {
_log_err(LOG_CRIT, pamh,
"close_session - error recovering username");
return PAM_SESSION_ERR; /* How did we get authenticated with
no username?! */
}
retval = pam_get_item(pamh, PAM_SERVICE, (void *) &service);
- if (service == NULL || retval != PAM_SUCCESS) {
+ if (service == NULL || *service == '\0' || retval != PAM_SUCCESS) {
_log_err(LOG_CRIT, pamh,
"close_session - error recovering service");
return PAM_SESSION_ERR;
diff --git a/Linux-PAM/modules/pam_unix/support.c b/Linux-PAM/modules/pam_unix/support.c
index 15861af6..1584f2f1 100644
--- a/Linux-PAM/modules/pam_unix/support.c
+++ b/Linux-PAM/modules/pam_unix/support.c
@@ -1,5 +1,5 @@
/*
- * $Id: support.c,v 1.1.1.2 2002/09/15 20:09:02 hartmans Exp $
+ * $Id: support.c,v 1.25 2005/01/10 09:45:37 kukuk Exp $
*
* Copyright information at end of file.
*/
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
+#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <pwd.h>
@@ -16,9 +17,13 @@
#include <limits.h>
#include <utmp.h>
#include <errno.h>
+#include <signal.h>
+#include <ctype.h>
+#include <rpcsvc/ypclnt.h>
#include <security/_pam_macros.h>
#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
#include "md5.h"
#include "support.h"
@@ -106,36 +111,6 @@ int _make_remark(pam_handle_t * pamh, unsigned int ctrl
return retval;
}
- /*
- * Beacause getlogin() is braindead and sometimes it just
- * doesn't work, we reimplement it here.
- */
-char *PAM_getlogin(void)
-{
- struct utmp *ut, line;
- char *curr_tty, *retval;
- static char curr_user[sizeof(ut->ut_user) + 4];
-
- retval = NULL;
-
- curr_tty = ttyname(0);
- if (curr_tty != NULL) {
- D(("PAM_getlogin ttyname: %s", curr_tty));
- curr_tty += 5;
- setutent();
- strncpy(line.ut_line, curr_tty, sizeof(line.ut_line));
- if ((ut = getutline(&line)) != NULL) {
- strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user));
- curr_user[sizeof(curr_user) - 1] = '\0';
- retval = curr_user;
- }
- endutent();
- }
- D(("PAM_getlogin retval: %s", retval));
-
- return retval;
-}
-
/*
* set the control flags for the UNIX module.
*/
@@ -163,10 +138,6 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int argc,
D(("PRELIM_CHECK"));
set(UNIX__PRELIM, ctrl);
}
- if (flags & PAM_DISALLOW_NULL_AUTHTOK) {
- D(("DISALLOW_NULL_AUTHTOK"));
- set(UNIX__NONULL, ctrl);
- }
if (flags & PAM_SILENT) {
D(("SILENT"));
set(UNIX__QUIET, ctrl);
@@ -195,7 +166,7 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int argc,
if (remember != NULL) {
if (j == UNIX_REMEMBER_PASSWD) {
*remember = strtol(*argv + 9, NULL, 10);
- if ((*remember == LONG_MIN) || (*remember == LONG_MAX))
+ if ((*remember == INT_MIN) || (*remember == INT_MAX))
*remember = -1;
if (*remember > 400)
*remember = 400;
@@ -206,6 +177,11 @@ int _set_ctrl(pam_handle_t *pamh, int flags, int *remember, int argc,
++argv; /* step to next argument */
}
+ if (flags & PAM_DISALLOW_NULL_AUTHTOK) {
+ D(("DISALLOW_NULL_AUTHTOK"));
+ set(UNIX__NONULL, ctrl);
+ }
+
/* auditing is a more sensitive version of debug */
if (on(UNIX_AUDIT, ctrl)) {
@@ -304,25 +280,178 @@ static void _cleanup_failures(pam_handle_t * pamh, void *fl, int err)
}
/*
+ * _unix_getpwnam() searches only /etc/passwd and NIS to find user information
+ */
+static void _unix_cleanup(pam_handle_t *pamh, void *data, int error_status)
+{
+ free(data);
+}
+
+int _unix_getpwnam(pam_handle_t *pamh, const char *name,
+ int files, int nis, struct passwd **ret)
+{
+ FILE *passwd;
+ char buf[16384];
+ int matched = 0, buflen;
+ char *slogin, *spasswd, *suid, *sgid, *sgecos, *shome, *sshell, *p;
+
+ memset(buf, 0, sizeof(buf));
+
+ if (!matched && files) {
+ int userlen = strlen(name);
+ passwd = fopen("/etc/passwd", "r");
+ if (passwd != NULL) {
+ while (fgets(buf, sizeof(buf), passwd) != NULL) {
+ if ((buf[userlen] == ':') &&
+ (strncmp(name, buf, userlen) == 0)) {
+ p = buf + strlen(buf) - 1;
+ while (isspace(*p) && (p >= buf)) {
+ *p-- = '\0';
+ }
+ matched = 1;
+ break;
+ }
+ }
+ fclose(passwd);
+ }
+ }
+
+ if (!matched && nis) {
+ char *userinfo = NULL, *domain = NULL;
+ int len = 0, i;
+ len = yp_get_default_domain(&domain);
+ if (len == YPERR_SUCCESS) {
+ len = yp_bind(domain);
+ }
+ if (len == YPERR_SUCCESS) {
+ i = yp_match(domain, "passwd.byname", name,
+ strlen(name), &userinfo, &len);
+ yp_unbind(domain);
+ if ((i == YPERR_SUCCESS) && (len < sizeof(buf))) {
+ strncpy(buf, userinfo, sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = '\0';
+ matched = 1;
+ }
+ }
+ }
+
+ if (matched && (ret != NULL)) {
+ *ret = NULL;
+
+ slogin = buf;
+
+ spasswd = strchr(slogin, ':');
+ if (spasswd == NULL) {
+ return matched;
+ }
+ *spasswd++ = '\0';
+
+ suid = strchr(spasswd, ':');
+ if (suid == NULL) {
+ return matched;
+ }
+ *suid++ = '\0';
+
+ sgid = strchr(suid, ':');
+ if (sgid == NULL) {
+ return matched;
+ }
+ *sgid++ = '\0';
+
+ sgecos = strchr(sgid, ':');
+ if (sgecos == NULL) {
+ return matched;
+ }
+ *sgecos++ = '\0';
+
+ shome = strchr(sgecos, ':');
+ if (shome == NULL) {
+ return matched;
+ }
+ *shome++ = '\0';
+
+ sshell = strchr(shome, ':');
+ if (sshell == NULL) {
+ return matched;
+ }
+ *sshell++ = '\0';
+
+ buflen = sizeof(struct passwd) +
+ strlen(slogin) + 1 +
+ strlen(spasswd) + 1 +
+ strlen(suid) + 1 +
+ strlen(sgid) + 1 +
+ strlen(sgecos) + 1 +
+ strlen(shome) + 1 +
+ strlen(sshell) + 1;
+ *ret = malloc(buflen);
+ if (*ret == NULL) {
+ return matched;
+ }
+ memset(*ret, '\0', buflen);
+
+ (*ret)->pw_uid = strtol(suid, &p, 10);
+ if ((strlen(sgid) == 0) || (*p != '\0')) {
+ free(*ret);
+ *ret = NULL;
+ return matched;
+ }
+
+ (*ret)->pw_gid = strtol(sgid, &p, 10);
+ if ((strlen(sgid) == 0) || (*p != '\0')) {
+ free(*ret);
+ *ret = NULL;
+ return matched;
+ }
+
+ p = ((char*)(*ret)) + sizeof(struct passwd);
+ (*ret)->pw_name = strcpy(p, slogin);
+ p += strlen(p) + 1;
+ (*ret)->pw_passwd = strcpy(p, spasswd);
+ p += strlen(p) + 1;
+ (*ret)->pw_gecos = strcpy(p, sgecos);
+ p += strlen(p) + 1;
+ (*ret)->pw_dir = strcpy(p, shome);
+ p += strlen(p) + 1;
+ (*ret)->pw_shell = strcpy(p, sshell);
+
+ snprintf(buf, sizeof(buf), "_pam_unix_getpwnam_%s", name);
+
+ if (pam_set_data(pamh, buf,
+ *ret, _unix_cleanup) != PAM_SUCCESS) {
+ free(*ret);
+ *ret = NULL;
+ }
+ }
+
+ return matched;
+}
+
+/*
+ * _unix_comsefromsource() is a quick check to see if information about a given
+ * user comes from a particular source (just files and nis for now)
+ *
+ */
+int _unix_comesfromsource(pam_handle_t *pamh,
+ const char *name, int files, int nis)
+{
+ return _unix_getpwnam(pamh, name, files, nis, NULL);
+}
+
+/*
* _unix_blankpasswd() is a quick check for a blank password
*
* returns TRUE if user does not have a password
* - to avoid prompting for one in such cases (CG)
*/
-int _unix_blankpasswd(unsigned int ctrl, const char *name)
+int
+_unix_blankpasswd (pam_handle_t *pamh, unsigned int ctrl, const char *name)
{
struct passwd *pwd = NULL;
struct spwd *spwdent = NULL;
char *salt = NULL;
int retval;
-#if HAVE_GETPWNAM_R
- char *buf = NULL;
- int bufsize = 0;
- struct passwd pwd_buf;
-
- pwd = &pwd_buf;
-#endif
D(("called"));
@@ -338,23 +467,7 @@ int _unix_blankpasswd(unsigned int ctrl, const char *name)
/* UNIX passwords area */
/* Get password file entry... */
-#if HAVE_GETPWNAM_R
- bufsize = 1024;
- buf = malloc(bufsize);
-
- if ((retval = getpwnam_r(name, pwd, buf, bufsize, &pwd))) {
- pwd = NULL;
- }
- while (retval == ERANGE) {
- bufsize += 1024;
- buf = realloc(buf, bufsize);
- if ((retval = getpwnam_r(name, pwd, buf, bufsize, &pwd))) {
- pwd = NULL;
- }
- }
-#else
- pwd = getpwnam(name);
-#endif
+ pwd = _pammodutil_getpwnam (pamh, name);
if (pwd != NULL) {
if (strcmp( pwd->pw_passwd, "*NP*" ) == 0)
@@ -372,28 +485,24 @@ int _unix_blankpasswd(unsigned int ctrl, const char *name)
setreuid( 0, -1 );
if(setreuid( -1, pwd->pw_uid ) == -1)
/* Will fail elsewhere. */
-#if HAVE_GETPWNAM_R
- if (buf)
- free(buf);
-#endif
return 0;
}
}
- spwdent = getspnam( name );
+ spwdent = _pammodutil_getspnam (pamh, name);
if (save_uid == pwd->pw_uid)
setreuid( save_uid, save_euid );
else {
if (setreuid( -1, 0 ) == -1)
- setreuid( save_uid, -1 );
+ setreuid( save_uid, -1 );
setreuid( -1, save_euid );
}
- } else if (strcmp(pwd->pw_passwd, "x") == 0) {
+ } else if (_unix_shadowed(pwd)) {
/*
* ...and shadow password file entry for this user,
* if shadowing is enabled
*/
- spwdent = getspnam(name);
+ spwdent = _pammodutil_getspnam(pamh, name);
}
if (spwdent)
salt = x_strdup(spwdent->sp_pwdp);
@@ -415,11 +524,6 @@ int _unix_blankpasswd(unsigned int ctrl, const char *name)
if (salt)
_pam_delete(salt);
-#if HAVE_GETPWNAM_R
- if (buf)
- free(buf);
-#endif
-
return retval;
}
@@ -434,6 +538,7 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
unsigned int ctrl, const char *user)
{
int retval, child, fds[2];
+ void (*sighandler)(int) = NULL;
D(("called."));
/* create a pipe for the password */
@@ -442,6 +547,18 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
return PAM_AUTH_ERR;
}
+ if (off(UNIX_NOREAP, ctrl)) {
+ /*
+ * This code arranges that the demise of the child does not cause
+ * the application to receive a signal it is not expecting - which
+ * may kill the application or worse.
+ *
+ * The "noreap" module argument is provided so that the admin can
+ * override this behavior.
+ */
+ sighandler = signal(SIGCHLD, SIG_DFL);
+ }
+
/* fork */
child = fork();
if (child == 0) {
@@ -486,6 +603,10 @@ static int _unix_run_helper_binary(pam_handle_t *pamh, const char *passwd,
retval = PAM_AUTH_ERR;
}
+ if (sighandler != NULL) {
+ (void) signal(SIGCHLD, sighandler); /* restore old signal handler */
+ }
+
D(("returning %d", retval));
return retval;
}
@@ -514,7 +635,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
D(("locating user's record"));
/* UNIX passwords area */
- pwd = getpwnam(name); /* Get password file entry... */
+ pwd = _pammodutil_getpwnam (pamh, name); /* Get password file entry... */
if (pwd != NULL) {
if (strcmp( pwd->pw_passwd, "*NP*" ) == 0)
@@ -535,7 +656,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
}
}
- spwdent = getspnam( name );
+ spwdent = _pammodutil_getspnam (pamh, name);
if (save_uid == pwd->pw_uid)
setreuid( save_uid, save_euid );
else {
@@ -543,12 +664,12 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
setreuid( save_uid, -1 );
setreuid( -1, save_euid );
}
- } else if (strcmp(pwd->pw_passwd, "x") == 0) {
+ } else if (_unix_shadowed(pwd)) {
/*
* ...and shadow password file entry for this user,
* if shadowing is enabled
*/
- spwdent = getspnam(name);
+ spwdent = _pammodutil_getspnam (pamh, name);
}
if (spwdent)
salt = x_strdup(spwdent->sp_pwdp);
@@ -565,7 +686,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
}
retval = PAM_SUCCESS;
- if (pwd == NULL || salt == NULL || !strcmp(salt, "x")) {
+ if (pwd == NULL || salt == NULL || !strcmp(salt, "x") || ((salt[0] == '#') && (salt[1] == '#') && !strcmp(salt + 2, name))) {
if (geteuid()) {
/* we are not root perhaps this is the reason? Run helper */
D(("running helper binary"));
@@ -577,6 +698,11 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
}
} else {
D(("user's record unavailable"));
+ p = NULL;
+ if (pwd == NULL)
+ retval = PAM_USER_UNKNOWN;
+ else
+ retval = PAM_AUTHINFO_UNAVAIL;
if (on(UNIX_AUDIT, ctrl)) {
/* this might be a typo and the user has given a password
instead of a username. Careful with this. */
@@ -584,54 +710,58 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
"check pass; user (%s) unknown", name);
} else {
name = NULL;
- _log_err(LOG_ALERT, pamh,
- "check pass; user unknown");
+ if (on(UNIX_DEBUG, ctrl) || pwd == NULL) {
+ _log_err(LOG_ALERT, pamh,
+ "check pass; user unknown");
+ } else {
+ /* don't log failure as another pam module can succeed */
+ goto cleanup;
+ }
}
- p = NULL;
- retval = PAM_AUTHINFO_UNAVAIL;
}
} else {
- if (!strlen(salt)) {
- /* the stored password is NULL */
- if (off(UNIX__NONULL, ctrl)) { /* this means we've succeeded */
- D(("user has empty password - access granted"));
- retval = PAM_SUCCESS;
- } else {
- D(("user has empty password - access denied"));
- retval = PAM_AUTH_ERR;
- }
- } else if (!p) {
- retval = PAM_AUTH_ERR;
+ int salt_len = strlen(salt);
+ if (!salt_len) {
+ /* the stored password is NULL */
+ if (off(UNIX__NONULL, ctrl)) {/* this means we've succeeded */
+ D(("user has empty password - access granted"));
+ retval = PAM_SUCCESS;
} else {
- if (!strncmp(salt, "$1$", 3)) {
- pp = Goodcrypt_md5(p, salt);
- if (strcmp(pp, salt) != 0) {
- _pam_delete(pp);
- pp = Brokencrypt_md5(p, salt);
- }
- } else {
- pp = bigcrypt(p, salt);
- }
- p = NULL; /* no longer needed here */
+ D(("user has empty password - access denied"));
+ retval = PAM_AUTH_ERR;
+ }
+ } else if (!p || (*salt == '*') || (salt_len < 13)) {
+ retval = PAM_AUTH_ERR;
+ } else {
+ if (!strncmp(salt, "$1$", 3)) {
+ pp = Goodcrypt_md5(p, salt);
+ if (strcmp(pp, salt) != 0) {
+ _pam_delete(pp);
+ pp = Brokencrypt_md5(p, salt);
+ }
+ } else {
+ pp = bigcrypt(p, salt);
+ }
+ p = NULL; /* no longer needed here */
- /* the moment of truth -- do we agree with the password? */
- D(("comparing state of pp[%s] and salt[%s]", pp, salt));
+ /* the moment of truth -- do we agree with the password? */
+ D(("comparing state of pp[%s] and salt[%s]", pp, salt));
- /*
- * Note, we are comparing the bigcrypt of the password with
- * the contents of the password field. If the latter was
- * encrypted with regular crypt (and not bigcrypt) it will
- * have been truncated for storage relative to the output
- * of bigcrypt here. As such we need to compare only the
- * stored string with the subset of bigcrypt's result.
- * Bug 521314: The strncmp comparison is for legacy support.
- */
- if (strncmp(pp, salt, strlen(salt)) == 0) {
- retval = PAM_SUCCESS;
- } else {
- retval = PAM_AUTH_ERR;
- }
+ /*
+ * Note, we are comparing the bigcrypt of the password with
+ * the contents of the password field. If the latter was
+ * encrypted with regular crypt (and not bigcrypt) it will
+ * have been truncated for storage relative to the output
+ * of bigcrypt here. As such we need to compare only the
+ * stored string with the subset of bigcrypt's result.
+ * Bug 521314: The strncmp comparison is for legacy support.
+ */
+ if (strncmp(pp, salt, salt_len) == 0) {
+ retval = PAM_SUCCESS;
+ } else {
+ retval = PAM_AUTH_ERR;
}
+ }
}
if (retval == PAM_SUCCESS) {
@@ -649,10 +779,17 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
if (new != NULL) {
- new->user = x_strdup(name ? name : "");
+ const char *login_name;
+
+ login_name = _pammodutil_getlogin(pamh);
+ if (login_name == NULL) {
+ login_name = "";
+ }
+
+ new->user = x_strdup(name ? name : "");
new->uid = getuid();
new->euid = geteuid();
- new->name = x_strdup(PAM_getlogin()? PAM_getlogin() : "");
+ new->name = x_strdup(login_name);
/* any previous failures for this user ? */
pam_get_data(pamh, data_name, (const void **) &old);
@@ -702,6 +839,7 @@ int _unix_verify_password(pam_handle_t * pamh, const char *name
}
}
+cleanup:
if (data_name)
_pam_delete(data_name);
if (salt)
@@ -762,7 +900,7 @@ int _unix_read_password(pam_handle_t * pamh
return PAM_AUTHTOK_RECOVER_ERR; /* didn't work */
} else if (on(UNIX_USE_AUTHTOK, ctrl)
&& off(UNIX__OLD_PASSWD, ctrl)) {
- return PAM_AUTHTOK_RECOVER_ERR;
+ return PAM_AUTHTOK_ERR;
}
}
/*
@@ -884,6 +1022,21 @@ int _unix_read_password(pam_handle_t * pamh
return PAM_SUCCESS;
}
+int _unix_shadowed(const struct passwd *pwd)
+{
+ if (pwd != NULL) {
+ if (strcmp(pwd->pw_passwd, "x") == 0) {
+ return 1;
+ }
+ if ((pwd->pw_passwd[0] == '#') &&
+ (pwd->pw_passwd[1] == '#') &&
+ (strcmp(pwd->pw_name, pwd->pw_passwd + 2) == 0)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
/* ****************************************************************** *
* Copyright (c) Jan Rêkorajski 1999.
* Copyright (c) Andrew G. Morgan 1996-8.
diff --git a/Linux-PAM/modules/pam_unix/support.h b/Linux-PAM/modules/pam_unix/support.h
index 368a4e8f..39abadd5 100644
--- a/Linux-PAM/modules/pam_unix/support.h
+++ b/Linux-PAM/modules/pam_unix/support.h
@@ -1,10 +1,11 @@
/*
- * $Id: support.h,v 1.1.1.1 2001/04/29 04:17:41 hartmans Exp $
+ * $Id: support.h,v 1.8 2004/10/06 13:42:36 kukuk Exp $
*/
#ifndef _PAM_UNIX_SUPPORT_H
#define _PAM_UNIX_SUPPORT_H
+#include <pwd.h>
/*
* here is the string to inform the user that the new passwords they
@@ -80,8 +81,11 @@ typedef struct {
#define UNIX_BIGCRYPT 18 /* use DEC-C2 crypt()^x function */
#define UNIX_LIKE_AUTH 19 /* need to auth for setcred to work */
#define UNIX_REMEMBER_PASSWD 20 /* Remember N previous passwords */
+#define UNIX_NOREAP 21 /* don't reap child process */
+#define UNIX_BROKEN_SHADOW 22 /* ignore errors reading password aging
+ * information during acct management */
/* -------------- */
-#define UNIX_CTRLS_ 21 /* number of ctrl arguments defined */
+#define UNIX_CTRLS_ 23 /* number of ctrl arguments defined */
static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
@@ -110,6 +114,8 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
/* UNIX_BIGCRYPT */ {"bigcrypt", _ALL_ON_^(020000), 0400000},
/* UNIX_LIKE_AUTH */ {"likeauth", _ALL_ON_, 01000000},
/* UNIX_REMEMBER_PASSWD */ {"remember=", _ALL_ON_, 02000000},
+/* UNIX_NOREAP */ {"noreap", _ALL_ON_, 04000000},
+/* UNIX_BROKEN_SHADOW */ {"broken_shadow", _ALL_ON_, 010000000},
};
#define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag)
@@ -123,13 +129,18 @@ static const UNIX_Ctrls unix_args[UNIX_CTRLS_] =
_pam_drop(xx); \
}
-extern char *PAM_getlogin(void);
extern void _log_err(int err, pam_handle_t *pamh, const char *format,...);
extern int _make_remark(pam_handle_t * pamh, unsigned int ctrl
,int type, const char *text);
extern int _set_ctrl(pam_handle_t * pamh, int flags, int *remember, int argc,
const char **argv);
-extern int _unix_blankpasswd(unsigned int ctrl, const char *name);
+extern int _unix_getpwnam (pam_handle_t *pamh,
+ const char *name, int files, int nis,
+ struct passwd **ret);
+extern int _unix_comesfromsource (pam_handle_t *pamh,
+ const char *name, int files, int nis);
+extern int _unix_blankpasswd(pam_handle_t *pamh,unsigned int ctrl,
+ const char *name);
extern int _unix_verify_password(pam_handle_t * pamh, const char *name
,const char *p, unsigned int ctrl);
extern int _unix_read_password(pam_handle_t * pamh
@@ -139,6 +150,6 @@ extern int _unix_read_password(pam_handle_t * pamh
,const char *prompt2
,const char *data_name
,const char **pass);
+extern int _unix_shadowed(const struct passwd *pwd);
#endif /* _PAM_UNIX_SUPPORT_H */
-
diff --git a/Linux-PAM/modules/pam_unix/unix_chkpwd.c b/Linux-PAM/modules/pam_unix/unix_chkpwd.c
index 6188435f..be32348f 100644
--- a/Linux-PAM/modules/pam_unix/unix_chkpwd.c
+++ b/Linux-PAM/modules/pam_unix/unix_chkpwd.c
@@ -1,5 +1,5 @@
/*
- * $Id: unix_chkpwd.c,v 1.1.1.2 2002/09/15 20:09:02 hartmans Exp $
+ * $Id: unix_chkpwd.c,v 1.11 2004/11/16 14:27:42 toady Exp $
*
* This program is designed to run setuid(root) or with sufficient
* privilege to read all of the unix password databases. It is designed
@@ -57,8 +57,31 @@ static void _log_err(int err, const char *format,...)
closelog();
}
+static int _unix_shadowed(const struct passwd *pwd)
+{
+ char hashpass[1024];
+ if (pwd != NULL) {
+ if (strcmp(pwd->pw_passwd, "x") == 0) {
+ return 1;
+ }
+ if (strlen(pwd->pw_name) < sizeof(hashpass) - 2) {
+ strcpy(hashpass, "##");
+ strcpy(hashpass + 2, pwd->pw_name);
+ if (strcmp(pwd->pw_passwd, hashpass) == 0) {
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
static void su_sighandler(int sig)
{
+#ifndef SA_RESETHAND
+ /* emulate the behaviour of the SA_RESETHAND flag */
+ if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV )
+ signal(sig, SIG_DFL);
+#endif
if (sig > 0) {
_log_err(LOG_NOTICE, "caught signal %d.", sig);
exit(sig);
@@ -74,7 +97,9 @@ static void setup_signals(void)
*/
(void) memset((void *) &action, 0, sizeof(action));
action.sa_handler = su_sighandler;
+#ifdef SA_RESETHAND
action.sa_flags = SA_RESETHAND;
+#endif
(void) sigaction(SIGILL, &action, NULL);
(void) sigaction(SIGTRAP, &action, NULL);
(void) sigaction(SIGBUS, &action, NULL);
@@ -87,20 +112,21 @@ static void setup_signals(void)
(void) sigaction(SIGQUIT, &action, NULL);
}
-static int _unix_verify_password(const char *name, const char *p, int opt)
+static int _unix_verify_password(const char *name, const char *p, int nullok)
{
struct passwd *pwd = NULL;
struct spwd *spwdent = NULL;
char *salt = NULL;
char *pp = NULL;
int retval = UNIX_FAILED;
+ int salt_len;
/* UNIX passwords area */
setpwent();
pwd = getpwnam(name); /* Get password file entry... */
endpwent();
if (pwd != NULL) {
- if (strcmp(pwd->pw_passwd, "x") == 0) {
+ if (_unix_shadowed(pwd)) {
/*
* ...and shadow password file entry for this user,
* if shadowing is enabled
@@ -133,8 +159,11 @@ static int _unix_verify_password(const char *name, const char *p, int opt)
return retval;
}
- if (strlen(salt) == 0)
- return (opt == 0) ? UNIX_FAILED : UNIX_PASSED;
+ salt_len = strlen(salt);
+ if (salt_len == 0)
+ return (nullok == 0) ? UNIX_FAILED : UNIX_PASSED;
+ else if (p == NULL || strlen(p) == 0)
+ return UNIX_FAILED;
/* the moment of truth -- do we agree with the password? */
retval = UNIX_FAILED;
@@ -147,6 +176,8 @@ static int _unix_verify_password(const char *name, const char *p, int opt)
if (strcmp(pp, salt) == 0)
retval = UNIX_PASSED;
}
+ } else if ((*salt == '*') || (salt_len < 13)) {
+ retval = UNIX_FAILED;
} else {
pp = bigcrypt(p, salt);
/*
@@ -158,7 +189,7 @@ static int _unix_verify_password(const char *name, const char *p, int opt)
* stored string with the subset of bigcrypt's result.
* Bug 521314: the strncmp comparison is for legacy support.
*/
- if (strncmp(pp, salt, strlen(salt)) == 0) {
+ if (strncmp(pp, salt, salt_len) == 0) {
retval = UNIX_PASSED;
}
}
@@ -197,7 +228,7 @@ int main(int argc, char *argv[])
{
char pass[MAXPASS + 1];
char option[8];
- int npass, opt;
+ int npass, nullok;
int force_failure = 0;
int retval = UNIX_FAILED;
char *user;
@@ -250,9 +281,9 @@ int main(int argc, char *argv[])
} else {
option[7] = '\0';
if (strncmp(option, "nullok", 8) == 0)
- opt = 1;
+ nullok = 1;
else
- opt = 0;
+ nullok = 0;
}
/* read the password from stdin (a pipe from the pam_unix module) */
@@ -271,13 +302,13 @@ int main(int argc, char *argv[])
if (npass == 0) {
/* the password is NULL */
- retval = _unix_verify_password(user, NULL, opt);
+ retval = _unix_verify_password(user, NULL, nullok);
} else {
/* does pass agree with the official one? */
pass[npass] = '\0'; /* NUL terminate */
- retval = _unix_verify_password(user, pass, opt);
+ retval = _unix_verify_password(user, pass, nullok);
}
}
diff --git a/Linux-PAM/modules/pam_userdb/Makefile b/Linux-PAM/modules/pam_userdb/Makefile
index bb774ddb..4da7310d 100644
--- a/Linux-PAM/modules/pam_userdb/Makefile
+++ b/Linux-PAM/modules/pam_userdb/Makefile
@@ -3,7 +3,7 @@
# Linux-PAM. You should not modify this Makefile (unless you know
# what you are doing!).
-# $Id: Makefile,v 1.1.1.2 2002/09/15 20:09:02 hartmans Exp $
+# $Id: Makefile,v 1.6 2004/09/14 14:22:40 kukuk Exp $
# Created by Cristian Gafton <gafton@redhat.com>
include ../../Make.Rules
@@ -24,6 +24,10 @@ else
endif
endif
+ifeq ($(HAVE_LIBCRYPT),yes)
+ MODULE_SIMPLE_EXTRALIBS += -lcrypt
+endif
+
ifeq ($(WHICH_DB),none)
include ../dont_makefile
diff --git a/Linux-PAM/modules/pam_userdb/README b/Linux-PAM/modules/pam_userdb/README
index f4423781..1cab7b74 100644
--- a/Linux-PAM/modules/pam_userdb/README
+++ b/Linux-PAM/modules/pam_userdb/README
@@ -1,6 +1,7 @@
pam_userdb:
Look up users in a .db database and verify their password against
- what is contained in that database.
+ what is contained in that database. The database will have been
+ created using db_load.
RECOGNIZED ARGUMENTS:
debug write a message to syslog indicating success or
@@ -8,16 +9,46 @@ RECOGNIZED ARGUMENTS:
db=[path] use the [path] database for performing lookup. There
is no default; the module will return PAM_IGNORE if
- no database is provided.
+ no database is provided. Some versions of DB will
+ automatically append ".db" to whatever pathname you
+ supply here.
+ crypt=[mode] indicates whether encrypted or plaintext passwords
+ are stored in the database. If [mode] is "crypt",
+ passwords should be stored in the database in
+ crypt(3) form. If [mode] is "none" or any other
+ value, passwords should be stored in the database in
+ plaintext.
+
icase make the password verification to be case insensitive
(ie when working with registration numbers and such)
+ only works with plaintext password storage.
dump dump all the entries in the database to the log (eek,
don't do this by default!)
+ use_authtok use the authentication token previously obtained by
+ another module that did the conversation with the
+ application. If this token can not be obtained then
+ the module will try to converse again. This option can
+ be used for stacking different modules that need to
+ deal with the authentication tokens.
+
+ unknown_ok do not return error when checking for a user that is
+ not in the database. This can be used to stack more
+ than one pam_userdb module that will check a
+ username/password pair in more than a database.
+
+ key_only the username and password are concatenated together
+ in the database hash as 'username-password' with a
+ random value. if the concatenation of the username and
+ password with a dash in the middle returns any result,
+ the user is valid. this is useful in cases where
+ the username may not be unique but the username and
+ password pair are.
+
MODULE SERVICES PROVIDED:
- auth _authetication and _setcred (blank)
+ auth _authentication and _setcred (blank)
EXAMPLE USE:
auth sufficient pam_userdb.so icase db=/tmp/dbtest.db
@@ -27,4 +58,4 @@ AUTHOR:
-$Id: README,v 1.1.1.1 2001/04/29 04:17:42 hartmans Exp $
+$Id: README,v 1.3 2004/09/28 13:48:47 kukuk Exp $
diff --git a/Linux-PAM/modules/pam_userdb/conv.c b/Linux-PAM/modules/pam_userdb/conv.c
index 0f13d03a..de5d12f2 100644
--- a/Linux-PAM/modules/pam_userdb/conv.c
+++ b/Linux-PAM/modules/pam_userdb/conv.c
@@ -5,8 +5,6 @@
/* $Id */
/* Copyright at the end of the file */
-#define _BSD_SOURCE
-
#include <stdlib.h>
#include <string.h>
diff --git a/Linux-PAM/modules/pam_userdb/create.pl b/Linux-PAM/modules/pam_userdb/create.pl
index 2668ef4a..28088102 100644
--- a/Linux-PAM/modules/pam_userdb/create.pl
+++ b/Linux-PAM/modules/pam_userdb/create.pl
@@ -2,12 +2,12 @@
# this program creates a database in ARGV[1] from pairs given on
# stdandard input
#
-# $Id: create.pl,v 1.1.1.1 2001/04/29 04:17:42 hartmans Exp $
+# $Id: create.pl,v 1.2 2004/09/28 13:48:47 kukuk Exp $
use DB_File;
my $database = $ARGV[0];
-die "Use: check,pl <database>\n" unless ($database);
+die "Use: create.pl <database>\n" unless ($database);
print "Using database: $database\n";
my %lusers = ();
diff --git a/Linux-PAM/modules/pam_userdb/pam_userdb.c b/Linux-PAM/modules/pam_userdb/pam_userdb.c
index 337d217b..86c7238b 100644
--- a/Linux-PAM/modules/pam_userdb/pam_userdb.c
+++ b/Linux-PAM/modules/pam_userdb/pam_userdb.c
@@ -1,13 +1,14 @@
/* pam_userdb module */
-
+
/*
- * $Id: pam_userdb.c,v 1.1.1.2 2002/09/15 20:09:03 hartmans Exp $
+ * $Id: pam_userdb.c,v 1.7 2004/09/28 13:48:47 kukuk Exp $
* Written by Cristian Gafton <gafton@redhat.com> 1996/09/10
* See the end of the file for Copyright Information
*/
#include <security/_pam_aconf.h>
+#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
@@ -56,33 +57,53 @@ static void _pam_log(int err, const char *format, ...)
closelog();
}
-char * database = NULL;
-static int ctrl = 0;
-
-static int _pam_parse(int argc, const char **argv)
+static int
+_pam_parse (int argc, const char **argv,
+ char **database, char **cryptmode)
{
- /* step through arguments */
- for (ctrl = 0; argc-- > 0; ++argv) {
-
- /* generic options */
-
- if (!strcmp(*argv,"debug"))
- ctrl |= PAM_DEBUG_ARG;
- else if (!strcasecmp(*argv, "icase"))
- ctrl |= PAM_ICASE_ARG;
- else if (!strcasecmp(*argv, "dump"))
- ctrl |= PAM_DUMP_ARG;
- else if (!strncasecmp(*argv,"db=", 3)) {
- database = strdup((*argv) + 3);
- if (database == NULL)
- _pam_log(LOG_ERR, "pam_parse: could not parse argument \"%s\"",
- *argv);
- } else {
- _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
- }
- }
+ int ctrl;
+
+ *database = NULL;
+ *cryptmode = NULL;
+
+ /* step through arguments */
+ for (ctrl = 0; argc-- > 0; ++argv)
+ {
+ /* generic options */
+
+ if (!strcmp(*argv,"debug"))
+ ctrl |= PAM_DEBUG_ARG;
+ else if (!strcasecmp(*argv, "icase"))
+ ctrl |= PAM_ICASE_ARG;
+ else if (!strcasecmp(*argv, "dump"))
+ ctrl |= PAM_DUMP_ARG;
+ else if (!strcasecmp(*argv, "unknown_ok"))
+ ctrl |= PAM_UNKNOWN_OK_ARG;
+ else if (!strcasecmp(*argv, "key_only"))
+ ctrl |= PAM_KEY_ONLY_ARG;
+ else if (!strncasecmp(*argv,"db=", 3))
+ {
+ *database = strdup((*argv) + 3);
+ if ((*database == NULL) || (strlen (*database) == 0))
+ _pam_log(LOG_ERR,
+ "pam_parse: could not parse argument \"%s\"",
+ *argv);
+ }
+ else if (!strncasecmp(*argv,"crypt=", 6))
+ {
+ *cryptmode = strdup((*argv) + 6);
+ if ((*cryptmode == NULL) || (strlen (*cryptmode) == 0))
+ _pam_log(LOG_ERR,
+ "pam_parse: could not parse argument \"%s\"",
+ *argv);
+ }
+ else
+ {
+ _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
+ }
+ }
- return ctrl;
+ return ctrl;
}
@@ -95,7 +116,9 @@ static int _pam_parse(int argc, const char **argv)
* -1 = Password incorrect
* -2 = System error
*/
-static int user_lookup(const char *user, const char *pass)
+static int
+user_lookup (const char *database, const char *cryptmode,
+ const char *user, const char *pass, int ctrl)
{
DBM *dbm;
datum key, data;
@@ -108,7 +131,8 @@ static int user_lookup(const char *user, const char *pass)
return -2;
}
- if (ctrl &PAM_DUMP_ARG) {
+ /* dump out the database contents for debugging */
+ if (ctrl & PAM_DUMP_ARG) {
_pam_log(LOG_INFO, "Database dump:");
for (key = dbm_firstkey(dbm); key.dptr != NULL;
key = dbm_nextkey(dbm)) {
@@ -116,14 +140,19 @@ static int user_lookup(const char *user, const char *pass)
_pam_log(LOG_INFO, "key[len=%d] = `%s', data[len=%d] = `%s'",
key.dsize, key.dptr, data.dsize, data.dptr);
}
- }
- /* do some more init work */
+ }
+ /* do some more init work */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
- key.dptr = x_strdup(user);
- key.dsize = strlen(user);
- user = NULL;
+ if (ctrl & PAM_KEY_ONLY_ARG) {
+ key.dptr = malloc(strlen(user) + 1 + strlen(pass) + 1);
+ sprintf(key.dptr, "%s-%s", user, pass);
+ key.dsize = strlen(key.dptr);
+ } else {
+ key.dptr = x_strdup(user);
+ key.dsize = strlen(user);
+ }
if (key.dptr) {
data = dbm_fetch(dbm, key);
@@ -138,27 +167,121 @@ static int user_lookup(const char *user, const char *pass)
if (data.dptr != NULL) {
int compare = 0;
-
+
+ if (ctrl & PAM_KEY_ONLY_ARG)
+ {
+ dbm_close (dbm);
+ return 0; /* found it, data contents don't matter */
+ }
+
+ if (strncasecmp(cryptmode, "crypt", 5) == 0) {
+
+ /* crypt(3) password storage */
+
+ char *cryptpw;
+ char salt[2];
+
+ if (data.dsize != 13) {
+ compare = -2;
+ } else if (ctrl & PAM_ICASE_ARG) {
+ compare = -2;
+ } else {
+ salt[0] = *data.dptr;
+ salt[1] = *(data.dptr + 1);
+
+ cryptpw = crypt (pass, salt);
+
+ if (cryptpw) {
+ compare = strncasecmp (data.dptr, cryptpw, data.dsize);
+ } else {
+ compare = -2;
+ if (ctrl & PAM_DEBUG_ARG) {
+ _pam_log(LOG_INFO, "crypt() returned NULL");
+ }
+ };
+
+ };
+
+ } else {
+
+ /* Unknown password encryption method -
+ * default to plaintext password storage
+ */
+
if (strlen(pass) != data.dsize) {
- compare = 1;
+ compare = 1; /* wrong password len -> wrong password */
} else if (ctrl & PAM_ICASE_ARG) {
compare = strncasecmp(data.dptr, pass, data.dsize);
} else {
compare = strncmp(data.dptr, pass, data.dsize);
}
+
+ if (strncasecmp(cryptmode, "none", 4) && ctrl & PAM_DEBUG_ARG) {
+ _pam_log(LOG_INFO, "invalid value for crypt parameter: %s",
+ cryptmode);
+ _pam_log(LOG_INFO, "defaulting to plaintext password mode");
+ }
+
+ }
+
dbm_close(dbm);
if (compare == 0)
return 0; /* match */
else
return -1; /* wrong */
} else {
- if (ctrl & PAM_DEBUG_ARG) {
+ int saw_user = 0;
+
+ if (ctrl & PAM_DEBUG_ARG) {
_pam_log(LOG_INFO, "error returned by dbm_fetch: %s",
strerror(errno));
}
- dbm_close(dbm);
+
/* probably we should check dbm_error() here */
- return 1; /* not found */
+
+ if ((ctrl & PAM_KEY_ONLY_ARG) == 0) {
+ dbm_close(dbm);
+ return 1; /* not key_only, so no entry => no entry for the user */
+ }
+
+ /* now handle the key_only case */
+ for (key = dbm_firstkey(dbm);
+ key.dptr != NULL;
+ key = dbm_nextkey(dbm)) {
+ int compare;
+ /* first compare the user portion (case sensitive) */
+ compare = strncmp(key.dptr, user, strlen(user));
+ if (compare == 0) {
+ /* assume failure */
+ compare = -1;
+ /* if we have the divider where we expect it to be... */
+ if (key.dptr[strlen(user)] == '-') {
+ saw_user = 1;
+ if (key.dsize == strlen(user) + 1 + strlen(pass)) {
+ if (ctrl & PAM_ICASE_ARG) {
+ /* compare the password portion (case insensitive)*/
+ compare = strncasecmp(key.dptr + strlen(user) + 1,
+ pass,
+ strlen(pass));
+ } else {
+ /* compare the password portion (case sensitive) */
+ compare = strncmp(key.dptr + strlen(user) + 1,
+ pass,
+ strlen(pass));
+ }
+ }
+ }
+ if (compare == 0) {
+ dbm_close(dbm);
+ return 0; /* match */
+ }
+ }
+ }
+ dbm_close(dbm);
+ if (saw_user)
+ return -1; /* saw the user, but password mismatch */
+ else
+ return 1; /* not found */
}
/* NOT REACHED */
@@ -173,10 +296,17 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
{
const char *username;
const char *password;
- int retval = PAM_AUTH_ERR;
-
+ char *database = NULL;
+ char *cryptmode = NULL;
+ int retval = PAM_AUTH_ERR, ctrl;
+
/* parse arguments */
- ctrl = _pam_parse(argc, argv);
+ ctrl = _pam_parse(argc, argv, &database, &cryptmode);
+ if ((database == NULL) || (strlen(database) == 0)) {
+ if (ctrl & PAM_DEBUG_ARG)
+ _pam_log(LOG_DEBUG,"can not get the database name");
+ return PAM_SERVICE_ERR;
+ }
/* Get the username */
retval = pam_get_user(pamh, &username, NULL);
@@ -185,32 +315,47 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
_pam_log(LOG_DEBUG,"can not get the username");
return PAM_SERVICE_ERR;
}
-
- /* Converse just to be sure we have the password */
+
+ /* Converse just to be sure we have a password */
retval = conversation(pamh);
if (retval != PAM_SUCCESS) {
_pam_log(LOG_ERR, "could not obtain password for `%s'",
username);
- return -2;
+ return PAM_CONV_ERR;
}
-
+
+ /* Check if we got a password. The docs say that if we didn't have one,
+ * and use_authtok was specified as an argument, that we converse with the
+ * user anyway, so check for one and handle a failure for that case. If
+ * use_authtok wasn't specified, then we've already asked once and needn't
+ * do so again. */
+ retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &password);
+ if ((retval != PAM_SUCCESS) && ((ctrl & PAM_USE_AUTHTOK_ARG) != 0)) {
+ retval = conversation(pamh);
+ if (retval != PAM_SUCCESS) {
+ _pam_log(LOG_ERR, "could not obtain password for `%s'",
+ username);
+ return PAM_CONV_ERR;
+ }
+ }
+
/* Get the password */
retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **)&password);
if (retval != PAM_SUCCESS) {
- _pam_log(LOG_ERR, "Could not retrive user's password");
+ _pam_log(LOG_ERR, "Could not retrieve user's password");
return -2;
}
-
+
if (ctrl & PAM_DEBUG_ARG)
_pam_log(LOG_INFO, "Verify user `%s' with password `%s'",
username, password);
-
+
/* Now use the username to look up password in the database file */
- retval = user_lookup(username, password);
+ retval = user_lookup(database, cryptmode, username, password, ctrl);
switch (retval) {
case -2:
/* some sort of system error. The log was already printed */
- return PAM_SERVICE_ERR;
+ return PAM_SERVICE_ERR;
case -1:
/* incorrect password */
_pam_log(LOG_WARNING,
@@ -247,9 +392,47 @@ int pam_sm_setcred(pam_handle_t *pamh, int flags,
}
PAM_EXTERN
-int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
- int argc, const char **argv)
+int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
+ const char *username;
+ char *database = NULL;
+ char *cryptmode = NULL;
+ int retval = PAM_AUTH_ERR, ctrl;
+
+ /* parse arguments */
+ ctrl = _pam_parse(argc, argv, &database, &cryptmode);
+
+ /* Get the username */
+ retval = pam_get_user(pamh, &username, NULL);
+ if ((retval != PAM_SUCCESS) || (!username)) {
+ if (ctrl & PAM_DEBUG_ARG)
+ _pam_log(LOG_DEBUG,"can not get the username");
+ return PAM_SERVICE_ERR;
+ }
+
+ /* Now use the username to look up password in the database file */
+ retval = user_lookup(database, cryptmode, username, "", ctrl);
+ switch (retval) {
+ case -2:
+ /* some sort of system error. The log was already printed */
+ return PAM_SERVICE_ERR;
+ case -1:
+ /* incorrect password, but we don't care */
+ /* FALL THROUGH */
+ case 0:
+ /* authentication succeeded. dumbest password ever. */
+ return PAM_SUCCESS;
+ case 1:
+ /* the user does not exist in the database */
+ return PAM_USER_UNKNOWN;
+ default:
+ /* we don't know anything about this return value */
+ _pam_log(LOG_ERR,
+ "internal module error (retval = %d, user = `%s'",
+ retval, username);
+ return PAM_SERVICE_ERR;
+ }
+
return PAM_SUCCESS;
}
@@ -262,7 +445,7 @@ struct pam_module _pam_userdb_modstruct = {
"pam_userdb",
pam_sm_authenticate,
pam_sm_setcred,
- NULL,
+ pam_sm_acct_mgmt,
NULL,
NULL,
NULL,
diff --git a/Linux-PAM/modules/pam_userdb/pam_userdb.h b/Linux-PAM/modules/pam_userdb/pam_userdb.h
index 88a93f0d..af03676b 100644
--- a/Linux-PAM/modules/pam_userdb/pam_userdb.h
+++ b/Linux-PAM/modules/pam_userdb/pam_userdb.h
@@ -1,7 +1,7 @@
#ifndef _PAM_USERSDB_H
#define _PAM_USERSDB_H
-/* $Id: pam_userdb.h,v 1.1.1.1 2001/04/29 04:17:42 hartmans Exp $ */
+/* $Id: pam_userdb.h,v 1.2 2004/09/28 13:48:47 kukuk Exp $ */
/* Header files */
#include <security/pam_appl.h>
@@ -10,6 +10,9 @@
#define PAM_DEBUG_ARG 0x0001
#define PAM_ICASE_ARG 0x0002
#define PAM_DUMP_ARG 0x0004
+#define PAM_USE_AUTHTOK_ARG 0x0008
+#define PAM_UNKNOWN_OK_ARG 0x0010
+#define PAM_KEY_ONLY_ARG 0x0020
/* Useful macros */
#define x_strdup(s) ( (s) ? strdup(s):NULL )
diff --git a/Linux-PAM/modules/pam_warn/Makefile b/Linux-PAM/modules/pam_warn/Makefile
index 657570e6..b1420538 100644
--- a/Linux-PAM/modules/pam_warn/Makefile
+++ b/Linux-PAM/modules/pam_warn/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:43 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:06 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_warn/README b/Linux-PAM/modules/pam_warn/README
index ab128179..3c4bde8a 100644
--- a/Linux-PAM/modules/pam_warn/README
+++ b/Linux-PAM/modules/pam_warn/README
@@ -1,4 +1,4 @@
-# $Id: README,v 1.1.1.1 2001/04/29 04:17:43 hartmans Exp $
+# $Id: README,v 1.1.1.1 2000/06/20 22:12:10 agmorgan Exp $
#
This module is an authentication module that does not authenticate.
diff --git a/Linux-PAM/modules/pam_warn/pam_warn.c b/Linux-PAM/modules/pam_warn/pam_warn.c
index f84490e8..90170c01 100644
--- a/Linux-PAM/modules/pam_warn/pam_warn.c
+++ b/Linux-PAM/modules/pam_warn/pam_warn.c
@@ -1,7 +1,7 @@
/* pam_warn module */
/*
- * $Id: pam_warn.c,v 1.1.1.2 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: pam_warn.c,v 1.2 2002/05/29 04:44:43 agmorgan Exp $
*
* Written by Andrew Morgan <morgan@linux.kernel.org> 1996/3/11
*/
diff --git a/Linux-PAM/modules/pam_wheel/Makefile b/Linux-PAM/modules/pam_wheel/Makefile
index e4f8a450..67947f81 100644
--- a/Linux-PAM/modules/pam_wheel/Makefile
+++ b/Linux-PAM/modules/pam_wheel/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2001/04/29 04:17:43 hartmans Exp $
+# $Id: Makefile,v 1.2 2000/11/19 23:54:06 agmorgan Exp $
#
# This Makefile controls a build process of $(TITLE) module for
# Linux-PAM. You should not modify this Makefile (unless you know
diff --git a/Linux-PAM/modules/pam_wheel/README b/Linux-PAM/modules/pam_wheel/README
index 336bb31e..2cd156c0 100644
--- a/Linux-PAM/modules/pam_wheel/README
+++ b/Linux-PAM/modules/pam_wheel/README
@@ -1,17 +1,17 @@
pam_wheel:
- only permit root authentication too members of wheel group
+ only permit root authentication to members of wheel group
RECOGNIZED ARGUMENTS:
- debug write a message to syslog indicating success or
+ debug Write a message to syslog indicating success or
failure.
- use_uid the check for wheel membership will be done against
+ use_uid The check for wheel membership will be done against
the current uid instead of the original one
(useful when jumping with su from one account to
- another for example)
-
- trust the pam_wheel module will return PAM_SUCCESS instead
+ another for example).
+
+ trust The pam_wheel module will return PAM_SUCCESS instead
of PAM_IGNORE if the user is a member of the wheel
group (thus with a little play stacking the modules
the wheel members may be able to su to root without
@@ -21,13 +21,19 @@ RECOGNIZED ARGUMENTS:
is trying to get UID 0 access and is a member of the
wheel group, deny access (well, kind of nonsense, but
for use in conjunction with 'group' argument... :-)
+ Conversely, if the user is not in the group, return
+ PAM_IGNORE (unless 'trust' was also specified, in
+ which case we return PAM_SUCCESS).
+
+ group=xxxx Instead of checking the wheel or GID 0 groups, use
+ the xxxx group to perform the authentification.
- group=xxxx Instead of checking the GID 0 group, use the xxxx
- group to perform the authentification.
+ root_only The check for wheel membership is done only
+ if the uid of requested account is 0.
MODULE SERVICES PROVIDED:
- auth _authetication and _setcred (blank)
+ auth _authentication, _setcred (blank) and _acct_mgmt
AUTHOR:
- Cristian Gafton <gafton@sorosis.ro>
+ Cristian Gafton <gafton@redhat.com>
diff --git a/Linux-PAM/modules/pam_wheel/pam_wheel.c b/Linux-PAM/modules/pam_wheel/pam_wheel.c
index d629819f..92cd44b9 100644
--- a/Linux-PAM/modules/pam_wheel/pam_wheel.c
+++ b/Linux-PAM/modules/pam_wheel/pam_wheel.c
@@ -40,8 +40,10 @@
*/
#define PAM_SM_AUTH
+#define PAM_SM_ACCOUNT
#include <security/pam_modules.h>
+#include <security/_pam_modutil.h>
/* some syslogging */
@@ -60,7 +62,7 @@ static void _pam_log(int err, const char *format, ...)
static int is_on_list(char * const *list, const char *member)
{
- while (*list) {
+ while (list && *list) {
if (strcmp(*list, member) == 0)
return 1;
list++;
@@ -73,7 +75,8 @@ static int is_on_list(char * const *list, const char *member)
#define PAM_DEBUG_ARG 0x0001
#define PAM_USE_UID_ARG 0x0002
#define PAM_TRUST_ARG 0x0004
-#define PAM_DENY_ARG 0x0010
+#define PAM_DENY_ARG 0x0010
+#define PAM_ROOT_ONLY_ARG 0x0020
static int _pam_parse(int argc, const char **argv, char *use_group,
size_t group_length)
@@ -95,6 +98,8 @@ static int _pam_parse(int argc, const char **argv, char *use_group,
ctrl |= PAM_TRUST_ARG;
else if (!strcmp(*argv,"deny"))
ctrl |= PAM_DENY_ARG;
+ else if (!strcmp(*argv,"root_only"))
+ ctrl |= PAM_ROOT_ONLY_ARG;
else if (!strncmp(*argv,"group=",6))
strncpy(use_group,*argv+6,group_length-1);
else {
@@ -105,139 +110,185 @@ static int _pam_parse(int argc, const char **argv, char *use_group,
return ctrl;
}
-
-/* --- authentication management functions (only) --- */
-
-PAM_EXTERN
-int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc
- ,const char **argv)
+static int perform_check(pam_handle_t *pamh, int flags, int ctrl,
+ const char *use_group)
{
- int ctrl;
- const char *username;
- char *fromsu;
- struct passwd *pwd, *tpwd;
- struct group *grp;
- int retval = PAM_AUTH_ERR;
- char use_group[BUFSIZ];
-
- /* Init the optional group */
- bzero(use_group,BUFSIZ);
-
- ctrl = _pam_parse(argc, argv, use_group, sizeof(use_group));
- retval = pam_get_user(pamh, &username, NULL);
- if ((retval != PAM_SUCCESS) || (!username)) {
- if (ctrl & PAM_DEBUG_ARG)
+ const char *username = NULL;
+ const char *fromsu;
+ struct passwd *pwd, *tpwd = NULL;
+ struct group *grp;
+ int retval = PAM_AUTH_ERR;
+
+ retval = pam_get_user(pamh, &username, NULL);
+ if ((retval != PAM_SUCCESS) || (!username)) {
+ if (ctrl & PAM_DEBUG_ARG) {
_pam_log(LOG_DEBUG,"can not get the username");
+ }
return PAM_SERVICE_ERR;
- }
+ }
- /* su to a uid 0 account ? */
- pwd = getpwnam(username);
- if (!pwd) {
- if (ctrl & PAM_DEBUG_ARG)
+ pwd = _pammodutil_getpwnam (pamh, username);
+ if (!pwd) {
+ if (ctrl & PAM_DEBUG_ARG) {
_pam_log(LOG_NOTICE,"unknown user %s",username);
+ }
return PAM_USER_UNKNOWN;
- }
+ }
+ if (ctrl & PAM_ROOT_ONLY_ARG) {
+ /* su to a non uid 0 account ? */
+ if (pwd->pw_uid != 0) {
+ return PAM_IGNORE;
+ }
+ }
- /* Now we know that the username exists, pass on to other modules...
- * the call to pam_get_user made this obsolete, so is commented out
- *
- * pam_set_item(pamh,PAM_USER,(const void *)username);
- */
-
- /* is this user an UID 0 account ? */
- if(pwd->pw_uid) {
- /* no need to check for wheel */
- return PAM_IGNORE;
- }
+ if (ctrl & PAM_USE_UID_ARG) {
+ tpwd = _pammodutil_getpwuid (pamh, getuid());
+ if (!tpwd) {
+ if (ctrl & PAM_DEBUG_ARG) {
+ _pam_log(LOG_NOTICE, "who is running me ?!");
+ }
+ return PAM_SERVICE_ERR;
+ }
+ fromsu = tpwd->pw_name;
+ } else {
+ fromsu = _pammodutil_getlogin(pamh);
+ if (fromsu) {
+ tpwd = _pammodutil_getpwnam (pamh, fromsu);
+ }
+ if (!fromsu || !tpwd) {
+ if (ctrl & PAM_DEBUG_ARG) {
+ _pam_log(LOG_NOTICE, "who is running me ?!");
+ }
+ return PAM_SERVICE_ERR;
+ }
+ }
+
+ /*
+ * At this point fromsu = username-of-invoker; tpwd = pwd ptr for fromsu
+ */
- if (ctrl & PAM_USE_UID_ARG) {
- tpwd = getpwuid(getuid());
- if (!tpwd) {
- if (ctrl & PAM_DEBUG_ARG)
- _pam_log(LOG_NOTICE,"who is running me ?!");
- return PAM_SERVICE_ERR;
- }
- fromsu = tpwd->pw_name;
- } else {
- fromsu = getlogin();
- if (!fromsu) {
- if (ctrl & PAM_DEBUG_ARG)
- _pam_log(LOG_NOTICE,"who is running me ?!");
- return PAM_SERVICE_ERR;
- }
- }
+ if (!use_group[0]) {
+ if ((grp = _pammodutil_getgrnam (pamh, "wheel")) == NULL) {
+ grp = _pammodutil_getgrgid (pamh, 0);
+ }
+ } else {
+ grp = _pammodutil_getgrnam (pamh, use_group);
+ }
+
+ if (!grp || (!grp->gr_mem && (tpwd->pw_gid != grp->gr_gid))) {
+ if (ctrl & PAM_DEBUG_ARG) {
+ if (!use_group[0]) {
+ _pam_log(LOG_NOTICE,"no members in a GID 0 group");
+ } else {
+ _pam_log(LOG_NOTICE,"no members in '%s' group", use_group);
+ }
+ }
+ if (ctrl & PAM_DENY_ARG) {
+ /* if this was meant to deny access to the members
+ * of this group and the group does not exist, allow
+ * access
+ */
+ return PAM_IGNORE;
+ } else {
+ return PAM_AUTH_ERR;
+ }
+ }
- if (!use_group[0]) {
- if ((grp = getgrnam("wheel")) == NULL) {
- grp = getgrgid(0);
- }
- } else
- grp = getgrnam(use_group);
-
- if (!grp || !grp->gr_mem) {
- if (ctrl & PAM_DEBUG_ARG) {
- if (!use_group[0])
- _pam_log(LOG_NOTICE,"no members in a GID 0 group");
- else
- _pam_log(LOG_NOTICE,"no members in '%s' group",use_group);
- }
- if (ctrl & PAM_DENY_ARG)
- /* if this was meant to deny access to the members
- * of this group and the group does not exist, allow
- * access
- */
- return PAM_IGNORE;
- else
- return PAM_AUTH_ERR;
- }
-
- if (is_on_list(grp->gr_mem, fromsu)) {
- if (ctrl & PAM_DEBUG_ARG)
- _pam_log(LOG_NOTICE,"Access %s to '%s' for '%s'",
- (ctrl & PAM_DENY_ARG)?"denied":"granted",
- fromsu,username);
- if (ctrl & PAM_DENY_ARG)
- return PAM_PERM_DENIED;
- else
- if (ctrl & PAM_TRUST_ARG)
- return PAM_SUCCESS;
- else
- return PAM_IGNORE;
- }
+ /*
+ * test if the user is a member of the group, or if the
+ * user has the "wheel" (sic) group as its primary group.
+ */
+
+ if (is_on_list(grp->gr_mem, fromsu) || (tpwd->pw_gid == grp->gr_gid)) {
+
+ if (ctrl & PAM_DENY_ARG) {
+ retval = PAM_PERM_DENIED;
+
+ } else if (ctrl & PAM_TRUST_ARG) {
+ retval = PAM_SUCCESS; /* this can be a sufficient check */
+
+ } else {
+ retval = PAM_IGNORE;
+ }
+
+ } else {
+
+ if (ctrl & PAM_DENY_ARG) {
+
+ if (ctrl & PAM_TRUST_ARG) {
+ retval = PAM_SUCCESS; /* this can be a sufficient check */
+ } else {
+ retval = PAM_IGNORE;
+ }
+
+ } else {
+ retval = PAM_PERM_DENIED;
+ }
+ }
+
+ if (ctrl & PAM_DEBUG_ARG) {
+ if (retval == PAM_IGNORE) {
+ _pam_log(LOG_NOTICE, "Ignoring access request '%s' for '%s'",
+ fromsu, username);
+ } else {
+ _pam_log(LOG_NOTICE, "Access %s to '%s' for '%s'",
+ (retval != PAM_SUCCESS) ? "denied":"granted",
+ fromsu, username);
+ }
+ }
- if (ctrl & PAM_DEBUG_ARG)
- _pam_log(LOG_NOTICE,"Access %s for '%s' to '%s'",
- (ctrl & PAM_DENY_ARG)?"granted":"denied",fromsu,username);
- if (ctrl & PAM_DENY_ARG)
- return PAM_SUCCESS;
- else
- return PAM_PERM_DENIED;
+ return retval;
+}
+
+/* --- authentication management functions --- */
+
+PAM_EXTERN
+int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ char use_group[BUFSIZ];
+ int ctrl;
+
+ ctrl = _pam_parse(argc, argv, use_group, sizeof(use_group));
+
+ return perform_check(pamh, flags, ctrl, use_group);
}
PAM_EXTERN
int pam_sm_setcred(pam_handle_t *pamh,int flags,int argc
,const char **argv)
{
- return PAM_SUCCESS;
+ return PAM_SUCCESS;
}
+PAM_EXTERN
+int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ char use_group[BUFSIZ];
+ int ctrl;
+
+ ctrl = _pam_parse(argc, argv, use_group, sizeof(use_group));
+
+ return perform_check(pamh, flags, ctrl, use_group);
+}
#ifdef PAM_STATIC
/* static module data */
struct pam_module _pam_wheel_modstruct = {
- "pam_wheel",
- pam_sm_authenticate,
- pam_sm_setcred,
- NULL,
- NULL,
- NULL,
- NULL,
+ "pam_wheel",
+ pam_sm_authenticate,
+ pam_sm_setcred,
+ pam_sm_acct_mgmt,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
};
-#endif
+#endif /* PAM_STATIC */
/*
* Copyright (c) Cristian Gafton <gafton@redhat.com>, 1996, 1997
diff --git a/Linux-PAM/modules/pam_xauth/Makefile b/Linux-PAM/modules/pam_xauth/Makefile
new file mode 100644
index 00000000..385466a2
--- /dev/null
+++ b/Linux-PAM/modules/pam_xauth/Makefile
@@ -0,0 +1,12 @@
+#
+# This Makefile controls a build process of $(TITLE) module for
+# Linux-PAM. You should not modify this Makefile (unless you know
+# what you are doing!).
+#
+
+include ../../Make.Rules
+
+TITLE=pam_xauth
+MAN8=pam_xauth.8
+
+include ../Simple.Rules
diff --git a/Linux-PAM/modules/pam_xauth/README b/Linux-PAM/modules/pam_xauth/README
new file mode 100644
index 00000000..dd65292f
--- /dev/null
+++ b/Linux-PAM/modules/pam_xauth/README
@@ -0,0 +1,41 @@
+pam_xauth:
+ Forward xauth cookies from user to user, normally used by su, sudo, or
+ userhelper.
+
+ Primitive access control is provided by ~/.xauth/export in the invoking
+ user's home directory and ~/.xauth/import in the target user's home
+ directory.
+
+ If a user has a ~/.xauth/import file, the user will only receive cookies
+ from users listed in the file. If there is no ~/.xauth/import file,
+ the user will accept cookies from any other user.
+
+ If a user has a .xauth/export file, the user will only forward cookies
+ to users listed in the file. If there is no ~/.xauth/export file, and
+ the invoking user is not "root", the user will forward cookies to
+ any other user. If there is no ~/.xauth/export file, and the invoking
+ user is "root", the user will NOT forward cookies to other users.
+
+ Both the import and export files support wildcards (such as "*"). Both
+ the import and export files can be empty, signifying that no users are
+ allowed.
+
+RECOGNIZED ARGUMENTS:
+ debug write debugging messages to syslog
+ xauthpath= the path to the xauth program, by default
+ /usr/X11R6/bin/xauth
+ systemuser= highest user id assigned to system users, defaults
+ to 499 (pam_xauth will refuse to forward creds to
+ target users with id equal to or below this number,
+ except for root and possibly another specified user)
+ targetuser= a target user id which is excepted from the systemuser
+ checks
+
+
+MODULE SERVICES PROVIDED:
+ session open session copies xauth cookie to new user
+ close session deletes copied xauth cookie
+
+AUTHOR:
+ Nalin Dahyabhai <nalin@redhat.com>, based on original version by
+ Michael K. Johnson <johnsonm@redhat.com>
diff --git a/Linux-PAM/modules/pam_xauth/pam_xauth.8 b/Linux-PAM/modules/pam_xauth/pam_xauth.8
new file mode 100644
index 00000000..9acb7249
--- /dev/null
+++ b/Linux-PAM/modules/pam_xauth/pam_xauth.8
@@ -0,0 +1,82 @@
+.\" Copyright 2001,2003 Red Hat, Inc.
+.\" Written by Nalin Dahyabhai <nalin@redhat.com>, based on the original
+.\" version by Michael K. Johnson
+.TH pam_xauth 8 2003/7/24 "Red Hat Linux" "System Administrator's Manual"
+.SH NAME
+pam_xauth \- forward xauth keys between users
+.SH SYNOPSIS
+.B session optional /lib/security/pam_xauth.so \fIarguments\fP
+.SH DESCRIPTION
+pam_xauth.so is designed to forward xauth keys (sometimes referred
+to as "cookies") between users.
+
+Without pam_xauth, when xauth is enabled and a user uses the \fBsu\fP command
+to assume another user's priviledges, that user is no longer able to access
+the original user's X display because the new user does not have the key
+needed to access the display. pam_xauth solves the problem by forwarding the
+key from the user running su (the source user) to the user whose
+identity the source user is assuming (the target user) when the session
+is created, and destroying the key when the session is torn down.
+
+This means, for example, that when you run \fBsu\fP from an xterm sesssion,
+you will be able to run X programs without explicitly dealing with the
+xauth command or ~/.Xauthority files.
+
+pam_xauth will only forward keys if xauth can list a key connected
+to the $DISPLAY environment variable.
+
+Primitive access control is provided by \fB~/.xauth/export\fP in the invoking
+user's home directory and \fB~/.xauth/import\fP in the target user's home
+directory.
+
+If a user has a \fB~/.xauth/import\fP file, the user will only receive cookies
+from users listed in the file. If there is no \fB~/.xauth/import\fP file,
+the user will accept cookies from any other user.
+
+If a user has a \fB.xauth/export\fP file, the user will only forward cookies
+to users listed in the file. If there is no \fB~/.xauth/export\fP file, and
+the invoking user is not \fBroot\fP, the user will forward cookies to
+any other user. If there is no \fB~/.xauth/export\fP file, and the invoking
+user is \fBroot\fP, the user will \fInot\fP forward cookies to other users.
+
+Both the import and export files support wildcards (such as \fI*\fP). Both
+the import and export files can be empty, signifying that no users are allowed.
+
+.SH ARGUMENTS
+.IP debug
+Turns on debugging messages sent to syslog.
+.IP xauthpath=\fI/usr/X11R6/bin/xauth\fP
+Specify the path the xauth program (the default is /usr/X11R6/bin/xauth).
+.IP systemuser=\fInumber\fP
+Specify the highest UID which will be assumed to belong to a "system" user.
+pam_xauth will refuse to forward credentials to users with UID less than or
+equal to this number, except for root and the "targetuser", if specified.
+.IP targetuser=\fInumber\fP
+Specify a single target UID which is exempt from the systemuser check.
+.SH "IMPLEMENTATION DETAILS"
+pam_xauth will work \fIonly\fP if it is used from a setuid application
+in which the getuid() call returns the id of the user running the
+application, and for which PAM can supply the name of the account that
+the user is attempting to assume. The typical application of this
+type is \fBsu\fP. The application must call both pam_open_session() and
+pam_close_session() with the ruid set to the uid of the calling user
+and the euid set to root, and must have provided as the PAM_USER item
+the name of the target user.
+
+pam_xauth calls \fBxauth\fP as the source user to extract the key for
+$DISPLAY, then calls xauth as the target user to merge the key
+into the a temporary database and later remove the database.
+
+pam_xauth cannot be told not to remove the keys when the session
+is closed.
+.SH "SEE ALSO"
+\fI/usr/share/doc/pam*/html/index.html\fP
+.SH FILES
+\fI~/.xauth/import\fP
+\fI~/.xauth/export\fP
+.SH BUGS
+Let's hope not, but if you find any, please report them via the "Bug Track"
+link at http://bugzilla.redhat.com/bugzilla/
+.SH AUTHOR
+Nalin Dahyabhai <nalin@redhat.com>, based on original version by
+Michael K. Johnson <johnsonm@redhat.com>
diff --git a/Linux-PAM/modules/pam_xauth/pam_xauth.c b/Linux-PAM/modules/pam_xauth/pam_xauth.c
new file mode 100644
index 00000000..2bf72eb6
--- /dev/null
+++ b/Linux-PAM/modules/pam_xauth/pam_xauth.c
@@ -0,0 +1,641 @@
+/*
+ * Copyright 2001-2003 Red Hat, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU Public License, in which case the provisions of the GPL are
+ * required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* "$Id: pam_xauth.c,v 1.4 2005/03/14 09:42:28 kukuk Exp $" */
+
+#include "../../_pam_aconf.h"
+#include <sys/types.h>
+#include <sys/fsuid.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fnmatch.h>
+#include <grp.h>
+#include <limits.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <security/pam_modules.h>
+#include <security/_pam_macros.h>
+#include <security/_pam_modutil.h>
+
+#define DATANAME "pam_xauth_cookie_file"
+#define XAUTHBIN "/usr/X11R6/bin/xauth"
+#define XAUTHENV "XAUTHORITY"
+#define HOMEENV "HOME"
+#define XAUTHDEF ".Xauthority"
+#define XAUTHTMP ".xauthXXXXXX"
+
+/* Run a given command (with a NULL-terminated argument list), feeding it the
+ * given input on stdin, and storing any output it generates. */
+static int
+run_coprocess(const char *input, char **output,
+ uid_t uid, gid_t gid, const char *command, ...)
+{
+ int ipipe[2], opipe[2], i;
+ char buf[LINE_MAX];
+ pid_t child;
+ char *buffer = NULL;
+ size_t buffer_size = 0;
+ va_list ap;
+
+ *output = NULL;
+
+ /* Create stdio pipery. */
+ if (pipe(ipipe) == -1) {
+ return -1;
+ }
+ if (pipe(opipe) == -1) {
+ close(ipipe[0]);
+ close(ipipe[1]);
+ return -1;
+ }
+
+ /* Fork off a child. */
+ child = fork();
+ if (child == -1) {
+ close(ipipe[0]);
+ close(ipipe[1]);
+ close(opipe[0]);
+ close(opipe[1]);
+ return -1;
+ }
+
+ if (child == 0) {
+ /* We're the child. */
+ char *args[10];
+ const char *tmp;
+ /* Drop privileges. */
+ setgid(gid);
+ setgroups(0, NULL);
+ setuid(uid);
+ /* Initialize the argument list. */
+ memset(args, 0, sizeof(args));
+ /* Set the pipe descriptors up as stdin and stdout, and close
+ * everything else, including the original values for the
+ * descriptors. */
+ dup2(ipipe[0], STDIN_FILENO);
+ dup2(opipe[1], STDOUT_FILENO);
+ for (i = 0; i < sysconf(_SC_OPEN_MAX); i++) {
+ if ((i != STDIN_FILENO) && (i != STDOUT_FILENO)) {
+ close(i);
+ }
+ }
+ /* Convert the varargs list into a regular array of strings. */
+ va_start(ap, command);
+ args[0] = strdup(command);
+ for (i = 1; i < ((sizeof(args) / sizeof(args[0])) - 1); i++) {
+ tmp = va_arg(ap, const char*);
+ if (tmp == NULL) {
+ break;
+ }
+ args[i] = strdup(tmp);
+ }
+ /* Run the command. */
+ execvp(command, args);
+ /* Never reached. */
+ exit(1);
+ }
+
+ /* We're the parent, so close the other ends of the pipes. */
+ close(ipipe[0]);
+ close(opipe[1]);
+ /* Send input to the process (if we have any), then send an EOF. */
+ if (input) {
+ (void)_pammodutil_write(ipipe[1], input, strlen(input));
+ }
+ close(ipipe[1]);
+
+ /* Read data output until we run out of stuff to read. */
+ i = _pammodutil_read(opipe[0], buf, sizeof(buf));
+ while ((i != 0) && (i != -1)) {
+ char *tmp;
+ /* Resize the buffer to hold the data. */
+ tmp = realloc(buffer, buffer_size + i + 1);
+ if (tmp == NULL) {
+ /* Uh-oh, bail. */
+ if (buffer != NULL) {
+ free(buffer);
+ }
+ close(opipe[0]);
+ waitpid(child, NULL, 0);
+ return -1;
+ }
+ /* Save the new buffer location, copy the newly-read data into
+ * the buffer, and make sure the result will be
+ * nul-terminated. */
+ buffer = tmp;
+ memcpy(buffer + buffer_size, buf, i);
+ buffer[buffer_size + i] = '\0';
+ buffer_size += i;
+ /* Try to read again. */
+ i = _pammodutil_read(opipe[0], buf, sizeof(buf));
+ }
+ /* No more data. Clean up and return data. */
+ close(opipe[0]);
+ *output = buffer;
+ waitpid(child, NULL, 0);
+ return 0;
+}
+
+/* Free a data item. */
+static void
+cleanup(pam_handle_t *pamh, void *data, int err)
+{
+ free(data);
+}
+
+/* Check if we want to allow export to the other user, or import from the
+ * other user. */
+static int
+check_acl(pam_handle_t *pamh,
+ const char *sense, const char *this_user, const char *other_user,
+ int noent_code, int debug)
+{
+ char path[PATH_MAX];
+ struct passwd *pwd;
+ FILE *fp;
+ int i;
+ uid_t euid;
+ /* Check this user's <sense> file. */
+ pwd = _pammodutil_getpwnam(pamh, this_user);
+ if (pwd == NULL) {
+ syslog(LOG_ERR, "pam_xauth: error determining "
+ "home directory for '%s'", this_user);
+ return PAM_SESSION_ERR;
+ }
+ /* Figure out what that file is really named. */
+ i = snprintf(path, sizeof(path), "%s/.xauth/%s", pwd->pw_dir, sense);
+ if ((i >= sizeof(path)) || (i < 0)) {
+ syslog(LOG_ERR, "pam_xauth: name of user's home directory "
+ "is too long");
+ return PAM_SESSION_ERR;
+ }
+ euid = geteuid();
+ setfsuid(pwd->pw_uid);
+ fp = fopen(path, "r");
+ setfsuid(euid);
+ if (fp != NULL) {
+ char buf[LINE_MAX], *tmp;
+ /* Scan the file for a list of specs of users to "trust". */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ tmp = memchr(buf, '\r', sizeof(buf));
+ if (tmp != NULL) {
+ *tmp = '\0';
+ }
+ tmp = memchr(buf, '\n', sizeof(buf));
+ if (tmp != NULL) {
+ *tmp = '\0';
+ }
+ if (fnmatch(buf, other_user, 0) == 0) {
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: %s %s "
+ "allowed by %s",
+ other_user, sense, path);
+ }
+ fclose(fp);
+ return PAM_SUCCESS;
+ }
+ }
+ /* If there's no match in the file, we fail. */
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: %s not listed in %s",
+ other_user, path);
+ }
+ fclose(fp);
+ return PAM_PERM_DENIED;
+ } else {
+ /* Default to okay if the file doesn't exist. */
+ switch (errno) {
+ case ENOENT:
+ if (noent_code == PAM_SUCCESS) {
+ if (debug) {
+ syslog(LOG_DEBUG, "%s does not exist, "
+ "ignoring", path);
+ }
+ } else {
+ if (debug) {
+ syslog(LOG_DEBUG, "%s does not exist, "
+ "failing", path);
+ }
+ }
+ return noent_code;
+ default:
+ if (debug) {
+ syslog(LOG_ERR, "%s opening %s",
+ strerror(errno), path);
+ }
+ return PAM_PERM_DENIED;
+ }
+ }
+}
+
+int
+pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ char xauthpath[] = XAUTHBIN;
+ char *cookiefile = NULL, *xauthority = NULL,
+ *cookie = NULL, *display = NULL, *tmp = NULL;
+ const char *user, *xauth = xauthpath;
+ struct passwd *tpwd, *rpwd;
+ int fd, i, debug = 0;
+ uid_t systemuser = 499, targetuser = 0, euid;
+
+ /* Parse arguments. We don't understand many, so no sense in breaking
+ * this into a separate function. */
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "debug") == 0) {
+ debug = 1;
+ continue;
+ }
+ if (strncmp(argv[i], "xauthpath=", 10) == 0) {
+ xauth = argv[i] + 10;
+ continue;
+ }
+ if (strncmp(argv[i], "targetuser=", 11) == 0) {
+ long l = strtol(argv[i] + 11, &tmp, 10);
+ if ((strlen(argv[i] + 11) > 0) && (*tmp == '\0')) {
+ targetuser = l;
+ } else {
+ syslog(LOG_WARNING, "pam_xauth: invalid value "
+ "for targetuser (`%s')", argv[i] + 11);
+ }
+ continue;
+ }
+ if (strncmp(argv[i], "systemuser=", 11) == 0) {
+ long l = strtol(argv[i] + 11, &tmp, 10);
+ if ((strlen(argv[i] + 11) > 0) && (*tmp == '\0')) {
+ systemuser = l;
+ } else {
+ syslog(LOG_WARNING, "pam_xauth: invalid value "
+ "for systemuser (`%s')", argv[i] + 11);
+ }
+ continue;
+ }
+ syslog(LOG_WARNING, "pam_xauth: unrecognized option `%s'",
+ argv[i]);
+ }
+
+ /* If DISPLAY isn't set, we don't really care, now do we? */
+ if ((display = getenv("DISPLAY")) == NULL) {
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: user has no DISPLAY,"
+ " doing nothing");
+ }
+ return PAM_SUCCESS;
+ }
+
+ /* Read the target user's name. */
+ if (pam_get_user(pamh, &user, NULL) != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_xauth: error determining target "
+ "user's name");
+ return PAM_SESSION_ERR;
+ }
+ rpwd = _pammodutil_getpwuid(pamh, getuid());
+ if (rpwd == NULL) {
+ syslog(LOG_ERR, "pam_xauth: error determining invoking "
+ "user's name");
+ return PAM_SESSION_ERR;
+ }
+
+ /* Get the target user's UID and primary GID, which we'll need to set
+ * on the xauthority file we create later on. */
+ tpwd = _pammodutil_getpwnam(pamh, user);
+ if (tpwd == NULL) {
+ syslog(LOG_ERR, "pam_xauth: error determining target "
+ "user's UID");
+ return PAM_SESSION_ERR;
+ }
+
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: requesting user %lu/%lu, "
+ "target user %lu/%lu",
+ (unsigned long) rpwd->pw_uid,
+ (unsigned long) rpwd->pw_gid,
+ (unsigned long) tpwd->pw_uid,
+ (unsigned long) tpwd->pw_gid);
+ }
+
+ /* If the UID is a system account (and not the superuser), forget
+ * about forwarding keys. */
+ if ((tpwd->pw_uid != 0) &&
+ (tpwd->pw_uid != targetuser) &&
+ (tpwd->pw_uid <= systemuser)) {
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: not forwarding cookies "
+ "to user ID %ld", (long) tpwd->pw_uid);
+ }
+ return PAM_SESSION_ERR;
+ }
+
+ /* Check that both users are amenable to this. By default, this
+ * boils down to this policy:
+ * export(ruser=root): only if <user> is listed in .xauth/export
+ * export(ruser=*) if <user> is listed in .xauth/export, or
+ * if .xauth/export does not exist
+ * import(user=*): if <ruser> is listed in .xauth/import, or
+ * if .xauth/import does not exist */
+ i = (getuid() != 0) ? PAM_SUCCESS : PAM_PERM_DENIED;
+ i = check_acl(pamh, "export", rpwd->pw_name, user, i, debug);
+ if (i != PAM_SUCCESS) {
+ return PAM_SESSION_ERR;
+ }
+ i = PAM_SUCCESS;
+ i = check_acl(pamh, "import", user, rpwd->pw_name, i, debug);
+ if (i != PAM_SUCCESS) {
+ return PAM_SESSION_ERR;
+ }
+
+ /* Figure out where the source user's .Xauthority file is. */
+ if (getenv(XAUTHENV) != NULL) {
+ cookiefile = strdup(getenv(XAUTHENV));
+ } else {
+ cookiefile = malloc(strlen(rpwd->pw_dir) + 1 +
+ strlen(XAUTHDEF) + 1);
+ if (cookiefile == NULL) {
+ return PAM_SESSION_ERR;
+ }
+ strcpy(cookiefile, rpwd->pw_dir);
+ strcat(cookiefile, "/");
+ strcat(cookiefile, XAUTHDEF);
+ }
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: reading keys from `%s'",
+ cookiefile);
+ }
+
+ /* Read the user's .Xauthority file. Because the current UID is
+ * the original user's UID, this will only fail if something has
+ * gone wrong, or we have no cookies. */
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: running \"%s %s %s %s %s\" as "
+ "%lu/%lu",
+ xauth,
+ "-f",
+ cookiefile,
+ "nlist",
+ display,
+ (unsigned long) getuid(),
+ (unsigned long) getgid());
+ }
+ if (run_coprocess(NULL, &cookie,
+ getuid(), getgid(),
+ xauth, "-f", cookiefile, "nlist", display,
+ NULL) == 0) {
+ /* Check that we got a cookie. If not, we get creative. */
+ if (((cookie == NULL) || (strlen(cookie) == 0)) &&
+ ((strncmp(display, "localhost:", 10) == 0) ||
+ (strncmp(display, "localhost/unix:", 15) == 0))) {
+ char *t, *screen;
+ size_t tlen, slen;
+ /* Free the useless cookie string. */
+ if (cookie != NULL) {
+ free(cookie);
+ cookie = NULL;
+ }
+ /* Allocate enough space to hold an adjusted name. */
+ tlen = strlen(display) + LINE_MAX + 1;
+ t = malloc(tlen);
+ if (t != NULL) {
+ memset(t, 0, tlen);
+ if (gethostname(t, tlen - 1) != -1) {
+ /* Append the protocol and then the
+ * screen number. */
+ if (strlen(t) < tlen - 6) {
+ strcat(t, "/unix:");
+ }
+ screen = strchr(display, ':');
+ if (screen != NULL) {
+ screen++;
+ slen = strlen(screen);
+ if (strlen(t) + slen < tlen) {
+ strcat(t, screen);
+ }
+ }
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: "
+ "no key for `%s', trying"
+ " `%s'", display, t);
+ }
+ /* Read the cookie for this display. */
+ if (debug) {
+ syslog(LOG_DEBUG,
+ "pam_xauth: running "
+ "\"%s %s %s %s %s\" as "
+ "%lu/%lu",
+ xauth,
+ "-f",
+ cookiefile,
+ "nlist",
+ t,
+ (unsigned long) getuid(),
+ (unsigned long) getgid());
+ }
+ run_coprocess(NULL, &cookie,
+ getuid(), getgid(),
+ xauth, "-f", cookiefile,
+ "nlist", t, NULL);
+ }
+ free(t);
+ t = NULL;
+ }
+ }
+
+ /* Check that we got a cookie, this time for real. */
+ if ((cookie == NULL) || (strlen(cookie) == 0)) {
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: no key");
+ }
+ return PAM_SESSION_ERR;
+ }
+
+ /* Generate the environment variable
+ * "XAUTHORITY=<homedir>/filename". */
+ xauthority = malloc(strlen(XAUTHENV) + 1 +
+ strlen(tpwd->pw_dir) + 1 +
+ strlen(XAUTHTMP) + 1);
+ if (xauthority == NULL) {
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: no free memory");
+ }
+ free(cookiefile);
+ free(cookie);
+ return PAM_SESSION_ERR;
+ }
+ strcpy(xauthority, XAUTHENV);
+ strcat(xauthority, "=");
+ strcat(xauthority, tpwd->pw_dir);
+ strcat(xauthority, "/");
+ strcat(xauthority, XAUTHTMP);
+
+ /* Generate a new file to hold the data. */
+ euid = geteuid();
+ setfsuid(tpwd->pw_uid);
+ fd = mkstemp(xauthority + strlen(XAUTHENV) + 1);
+ setfsuid(euid);
+ if (fd == -1) {
+ syslog(LOG_ERR, "pam_xauth: error creating "
+ "temporary file `%s': %s",
+ xauthority + strlen(XAUTHENV) + 1,
+ strerror(errno));
+ free(cookiefile);
+ free(cookie);
+ free(xauthority);
+ return PAM_SESSION_ERR;
+ }
+ /* Set permissions on the new file and dispose of the
+ * descriptor. */
+ fchown(fd, tpwd->pw_uid, tpwd->pw_gid);
+ close(fd);
+
+ /* Get a copy of the filename to save as a data item for
+ * removal at session-close time. */
+ free(cookiefile);
+ cookiefile = strdup(xauthority + strlen(XAUTHENV) + 1);
+
+ /* Save the filename. */
+ if (pam_set_data(pamh, DATANAME, cookiefile, cleanup) != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_xauth: error saving name of "
+ "temporary file `%s'", cookiefile);
+ unlink(cookiefile);
+ free(xauthority);
+ free(cookiefile);
+ free(cookie);
+ return PAM_SESSION_ERR;
+ }
+
+ /* Unset any old XAUTHORITY variable in the environment. */
+ if (getenv (XAUTHENV))
+ unsetenv (XAUTHENV);
+
+ /* Set the new variable in the environment. */
+ if (pam_putenv (pamh, xauthority) != PAM_SUCCESS)
+ syslog (LOG_DEBUG, "pam_xauth: can't set environment variable '%s'",
+ xauthority);
+ putenv (xauthority); /* The environment owns this string now. */
+
+ /* set $DISPLAY in pam handle to make su - work */
+ {
+ char *d = (char *) malloc (strlen ("DISPLAY=") +
+ strlen (display) + 1);
+ if (d == NULL)
+ {
+ syslog (LOG_DEBUG, "pam_xauth: memory exhausted\n");
+ return PAM_SESSION_ERR;
+ }
+ strcpy (d, "DISPLAY=");
+ strcat (d, display);
+
+ if (pam_putenv (pamh, d) != PAM_SUCCESS)
+ syslog (LOG_DEBUG,
+ "pam_xauth: can't set environment variable '%s'",
+ d);
+ free (d);
+ }
+
+ /* Merge the cookie we read before into the new file. */
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: writing key `%s' to "
+ "temporary file `%s'", cookie, cookiefile);
+ }
+ if (debug) {
+ syslog(LOG_DEBUG,
+ "pam_xauth: running \"%s %s %s %s %s\" as "
+ "%lu/%lu",
+ xauth,
+ "-f",
+ cookiefile,
+ "nmerge",
+ "-",
+ (unsigned long) tpwd->pw_uid,
+ (unsigned long) tpwd->pw_gid);
+ }
+ run_coprocess(cookie, &tmp,
+ tpwd->pw_uid, tpwd->pw_gid,
+ xauth, "-f", cookiefile, "nmerge", "-", NULL);
+
+ /* We don't need to keep a copy of these around any more. */
+ free(cookie);
+ cookie = NULL;
+ }
+ return PAM_SUCCESS;
+}
+
+int
+pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ void *cookiefile;
+ int i, debug = 0;
+
+ /* Parse arguments. We don't understand many, so no sense in breaking
+ * this into a separate function. */
+ for (i = 0; i < argc; i++) {
+ if (strcmp(argv[i], "debug") == 0) {
+ debug = 1;
+ continue;
+ }
+ if (strncmp(argv[i], "xauthpath=", 10) == 0) {
+ continue;
+ }
+ if (strncmp(argv[i], "systemuser=", 11) == 0) {
+ continue;
+ }
+ if (strncmp(argv[i], "targetuser=", 11) == 0) {
+ continue;
+ }
+ syslog(LOG_WARNING, "pam_xauth: unrecognized option `%s'",
+ argv[i]);
+ }
+
+ /* Try to retrieve the name of a file we created when the session was
+ * opened. */
+ if (pam_get_data(pamh, DATANAME, (const void**) &cookiefile) == PAM_SUCCESS) {
+ /* We'll only try to remove the file once. */
+ if (strlen((char*)cookiefile) > 0) {
+ if (debug) {
+ syslog(LOG_DEBUG, "pam_xauth: removing `%s'",
+ (char*)cookiefile);
+ }
+ unlink((char*)cookiefile);
+ *((char*)cookiefile) = '\0';
+ }
+ }
+ return PAM_SUCCESS;
+}
diff --git a/Linux-PAM/modules/pammodutil/Makefile b/Linux-PAM/modules/pammodutil/Makefile
index 03334326..bad1bf62 100644
--- a/Linux-PAM/modules/pammodutil/Makefile
+++ b/Linux-PAM/modules/pammodutil/Makefile
@@ -1,5 +1,5 @@
#
-# $Id: Makefile,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+# $Id: Makefile,v 1.4 2004/09/24 13:13:22 kukuk Exp $
#
#
@@ -18,7 +18,9 @@ CFLAGS += $(PIC) $(STATIC) $(MOREFLAGS) \
-DLIBPAM_VERSION_MINOR=$(MINOR_REL)
# all the object files we care about
-LIBOBJECTS = modutil_cleanup.o modutil_getpwnam.o modutil_getpwuid.o
+LIBOBJECTS = modutil_cleanup.o modutil_getpwnam.o modutil_getpwuid.o \
+ modutil_getspnam.o modutil_getgrnam.o modutil_getgrgid.o \
+ modutil_ingroup.o modutil_getlogin.o modutil_ioloop.o
# static library name
LIBSTATIC = $(LIBNAME).a
diff --git a/Linux-PAM/modules/pammodutil/README b/Linux-PAM/modules/pammodutil/README
index bd957247..ea44f310 100644
--- a/Linux-PAM/modules/pammodutil/README
+++ b/Linux-PAM/modules/pammodutil/README
@@ -1,4 +1,4 @@
-$Id: README,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+$Id: README,v 1.1 2001/12/09 22:15:12 agmorgan Exp $
This is a libarary of routines for use by modules. The routines seem
to have a common use for modules, but are not part of libpam and never
diff --git a/Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h b/Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h
index d36fcfa0..ec0c8964 100644
--- a/Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h
+++ b/Linux-PAM/modules/pammodutil/include/security/_pam_modutil.h
@@ -2,7 +2,7 @@
#define _PAM_MODUTIL_H
/*
- * $Id: _pam_modutil.h,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: _pam_modutil.h,v 1.4 2004/09/24 13:13:22 kukuk Exp $
*
* This file is a list of handy libc wrappers that attempt to provide some
* thread-safe and other convenient functionality to modules in a form that
@@ -15,10 +15,12 @@
* On systems that simply can't support thread safe programming, these
* functions don't support it either - sorry.
*
- * Copyright (c) 2001 Andrew Morgan <morgan@kernel.org>
+ * Copyright (c) 2001-2002 Andrew Morgan <morgan@kernel.org>
*/
#include <pwd.h>
+#include <grp.h>
+#include <shadow.h>
#include <sys/types.h>
extern struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh,
@@ -27,7 +29,38 @@ extern struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh,
extern struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh,
uid_t uid);
+extern struct group *_pammodutil_getgrnam(pam_handle_t *pamh,
+ const char *group);
+
+extern struct group *_pammodutil_getgrgid(pam_handle_t *pamh,
+ gid_t gid);
+
+extern struct spwd *_pammodutil_getspnam(pam_handle_t *pamh,
+ const char *user);
+
+extern int _pammodutil_user_in_group_nam_nam(pam_handle_t *pamh,
+ const char *user,
+ const char *group);
+
+extern int _pammodutil_user_in_group_nam_gid(pam_handle_t *pamh,
+ const char *user,
+ gid_t group);
+
+extern int _pammodutil_user_in_group_uid_nam(pam_handle_t *pamh,
+ uid_t user,
+ const char *group);
+
+extern int _pammodutil_user_in_group_uid_gid(pam_handle_t *pamh,
+ uid_t user,
+ gid_t group);
+
extern void _pammodutil_cleanup(pam_handle_t *pamh, void *data,
int error_status);
+extern const char *_pammodutil_getlogin(pam_handle_t *pamh);
+
+extern int _pammodutil_read(int fd, char *buffer, int count);
+
+extern int _pammodutil_write(int fd, const char *buffer, int count);
+
#endif /* _PAM_MODUTIL_H */
diff --git a/Linux-PAM/modules/pammodutil/modutil_cleanup.c b/Linux-PAM/modules/pammodutil/modutil_cleanup.c
index 76662133..5477481f 100644
--- a/Linux-PAM/modules/pammodutil/modutil_cleanup.c
+++ b/Linux-PAM/modules/pammodutil/modutil_cleanup.c
@@ -1,5 +1,5 @@
/*
- * $Id: modutil_cleanup.c,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: modutil_cleanup.c,v 1.1 2001/12/09 22:15:12 agmorgan Exp $
*
* This function provides a common pam_set_data() friendly version of free().
*/
diff --git a/Linux-PAM/modules/pammodutil/modutil_getgrgid.c b/Linux-PAM/modules/pammodutil/modutil_getgrgid.c
new file mode 100644
index 00000000..f97a9239
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_getgrgid.c
@@ -0,0 +1,150 @@
+/*
+ * $Id: modutil_getgrgid.c,v 1.3 2005/03/30 14:59:41 kukuk Exp $
+ *
+ * This function provides a thread safer version of getgrgid() for use
+ * with PAM modules that care about this sort of thing.
+ *
+ * XXX - or at least it should provide a thread-safe alternative.
+ */
+
+#include "pammodutil.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <grp.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static pthread_mutex_t _pammodutil_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void _pammodutil_lock(void)
+{
+ pthread_mutex_lock(&_pammodutil_mutex);
+}
+static void _pammodutil_unlock(void)
+{
+ pthread_mutex_unlock(&_pammodutil_mutex);
+}
+
+static int intlen(int number)
+{
+ int len = 2;
+ while (number != 0) {
+ number /= 10;
+ len++;
+ }
+ return len;
+}
+
+static int longlen(long number)
+{
+ int len = 2;
+ while (number != 0) {
+ number /= 10;
+ len++;
+ }
+ return len;
+}
+
+struct group *_pammodutil_getgrgid(pam_handle_t *pamh, gid_t gid)
+{
+#ifdef HAVE_GETGRGID_R
+
+ void *buffer=NULL;
+ size_t length = PWD_INITIAL_LENGTH;
+
+ do {
+ int status;
+ void *new_buffer;
+ struct group *result = NULL;
+
+ new_buffer = realloc(buffer, sizeof(struct group) + length);
+ if (new_buffer == NULL) {
+
+ D(("out of memory"));
+
+ /* no memory for the user - so delete the memory */
+ if (buffer) {
+ free(buffer);
+ }
+ return NULL;
+ }
+ buffer = new_buffer;
+
+ /* make the re-entrant call to get the grp structure */
+ errno = 0;
+ status = getgrgid_r(gid, buffer,
+ sizeof(struct group) + (char *) buffer,
+ length, &result);
+ if (!status && (result == buffer)) {
+ char *data_name;
+ const void *ignore;
+ int i;
+
+ data_name = malloc(strlen("_pammodutil_getgrgid") + 1 +
+ longlen((long)gid) + 1 + intlen(INT_MAX) + 1);
+ if ((pamh != NULL) && (data_name == NULL)) {
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+ free(buffer);
+ return NULL;
+ }
+
+ if (pamh != NULL) {
+ for (i = 0; i < INT_MAX; i++) {
+ sprintf(data_name, "_pammodutil_getgrgid_%ld_%d",
+ (long) gid, i);
+ _pammodutil_lock();
+ status = PAM_NO_MODULE_DATA;
+ if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
+ status = pam_set_data(pamh, data_name,
+ result, _pammodutil_cleanup);
+ }
+ _pammodutil_unlock();
+ if (status == PAM_SUCCESS) {
+ break;
+ }
+ }
+ } else {
+ status = PAM_SUCCESS;
+ }
+
+ free(data_name);
+
+ if (status == PAM_SUCCESS) {
+ D(("success"));
+ return result;
+ }
+
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+
+ free(buffer);
+ return NULL;
+
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
+
+ length <<= 2;
+
+ } while (length < PWD_ABSURD_PWD_LENGTH);
+
+ D(("grp structure took %u bytes or so of memory",
+ length+sizeof(struct group)));
+
+ free(buffer);
+ return NULL;
+
+#else /* ie. ifndef HAVE_GETGRGID_R */
+
+ /*
+ * Sorry, there does not appear to be a reentrant version of
+ * getgrgid(). So, we use the standard libc function.
+ */
+
+ return getgrgid(gid);
+
+#endif /* def HAVE_GETGRGID_R */
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_getgrnam.c b/Linux-PAM/modules/pammodutil/modutil_getgrnam.c
new file mode 100644
index 00000000..0727618c
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_getgrnam.c
@@ -0,0 +1,139 @@
+/*
+ * $Id: modutil_getgrnam.c,v 1.3 2005/03/30 14:59:41 kukuk Exp $
+ *
+ * This function provides a thread safer version of getgrnam() for use
+ * with PAM modules that care about this sort of thing.
+ *
+ * XXX - or at least it should provide a thread-safe alternative.
+ */
+
+#include "pammodutil.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <grp.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static pthread_mutex_t _pammodutil_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void _pammodutil_lock(void)
+{
+ pthread_mutex_lock(&_pammodutil_mutex);
+}
+static void _pammodutil_unlock(void)
+{
+ pthread_mutex_unlock(&_pammodutil_mutex);
+}
+
+static int intlen(int number)
+{
+ int len = 2;
+ while (number != 0) {
+ number /= 10;
+ len++;
+ }
+ return len;
+}
+
+struct group *_pammodutil_getgrnam(pam_handle_t *pamh, const char *group)
+{
+#ifdef HAVE_GETGRNAM_R
+
+ void *buffer=NULL;
+ size_t length = PWD_INITIAL_LENGTH;
+
+ do {
+ int status;
+ void *new_buffer;
+ struct group *result = NULL;
+
+ new_buffer = realloc(buffer, sizeof(struct group) + length);
+ if (new_buffer == NULL) {
+
+ D(("out of memory"));
+
+ /* no memory for the group - so delete the memory */
+ if (buffer) {
+ free(buffer);
+ }
+ return NULL;
+ }
+ buffer = new_buffer;
+
+ /* make the re-entrant call to get the grp structure */
+ errno = 0;
+ status = getgrnam_r(group, buffer,
+ sizeof(struct group) + (char *) buffer,
+ length, &result);
+ if (!status && (result == buffer)) {
+ char *data_name;
+ const void *ignore;
+ int i;
+
+ data_name = malloc(strlen("_pammodutil_getgrnam") + 1 +
+ strlen(group) + 1 + intlen(INT_MAX) + 1);
+ if ((pamh != NULL) && (data_name == NULL)) {
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+ free(buffer);
+ return NULL;
+ }
+
+ if (pamh != NULL) {
+ for (i = 0; i < INT_MAX; i++) {
+ sprintf(data_name, "_pammodutil_getgrnam_%s_%d", group, i);
+ _pammodutil_lock();
+ status = PAM_NO_MODULE_DATA;
+ if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
+ status = pam_set_data(pamh, data_name,
+ result, _pammodutil_cleanup);
+ }
+ _pammodutil_unlock();
+ if (status == PAM_SUCCESS) {
+ break;
+ }
+ }
+ } else {
+ status = PAM_SUCCESS;
+ }
+
+ free(data_name);
+
+ if (status == PAM_SUCCESS) {
+ D(("success"));
+ return result;
+ }
+
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+
+ free(buffer);
+ return NULL;
+
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
+
+ length <<= 2;
+
+ } while (length < PWD_ABSURD_PWD_LENGTH);
+
+ D(("grp structure took %u bytes or so of memory",
+ length+sizeof(struct group)));
+
+ free(buffer);
+ return NULL;
+
+#else /* ie. ifndef HAVE_GETGRNAM_R */
+
+ /*
+ * Sorry, there does not appear to be a reentrant version of
+ * getgrnam(). So, we use the standard libc function.
+ */
+
+ return getgrnam(group);
+
+#endif /* def HAVE_GETGRNAM_R */
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_getlogin.c b/Linux-PAM/modules/pammodutil/modutil_getlogin.c
new file mode 100644
index 00000000..0e4a48d8
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_getlogin.c
@@ -0,0 +1,72 @@
+/*
+ * $Id: modutil_getlogin.c,v 1.4 2004/11/08 10:57:15 t8m Exp $
+ *
+ * A central point for invoking getlogin(). Hopefully, this is a
+ * little harder to spoof than all the other versions that are out
+ * there.
+ */
+
+#include "pammodutil.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <utmp.h>
+
+#define _PAMMODUTIL_GETLOGIN "_pammodutil_getlogin"
+
+const char *_pammodutil_getlogin(pam_handle_t *pamh)
+{
+ int status;
+ char *logname;
+ const char *curr_tty;
+ char *curr_user;
+ struct utmp *ut, line;
+
+ status = pam_get_data(pamh, _PAMMODUTIL_GETLOGIN,
+ (const void **) &logname);
+ if (status == PAM_SUCCESS) {
+ return logname;
+ }
+
+ status = pam_get_item(pamh, PAM_TTY, (const void **) &curr_tty);
+ if ((status != PAM_SUCCESS) || (curr_tty == NULL)) {
+ curr_tty = ttyname(0);
+ }
+
+ if ((curr_tty == NULL) || memcmp(curr_tty, "/dev/", 5)) {
+ return NULL;
+ }
+
+ curr_tty += 5; /* strlen("/dev/") */
+ logname = NULL;
+
+ setutent();
+ strncpy(line.ut_line, curr_tty, sizeof(line.ut_line));
+
+ if ((ut = getutline(&line)) == NULL) {
+ goto clean_up_and_go_home;
+ }
+
+ curr_user = calloc(sizeof(line.ut_user)+1, 1);
+ if (curr_user == NULL) {
+ goto clean_up_and_go_home;
+ }
+
+ strncpy(curr_user, ut->ut_user, sizeof(ut->ut_user));
+ /* calloc already zeroed the memory */
+
+ status = pam_set_data(pamh, _PAMMODUTIL_GETLOGIN, curr_user,
+ _pammodutil_cleanup);
+ if (status != PAM_SUCCESS) {
+ free(curr_user);
+ goto clean_up_and_go_home;
+ }
+
+ logname = curr_user;
+
+clean_up_and_go_home:
+
+ endutent();
+
+ return logname;
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_getpwnam.c b/Linux-PAM/modules/pammodutil/modutil_getpwnam.c
index e3a8f270..eb359544 100644
--- a/Linux-PAM/modules/pammodutil/modutil_getpwnam.c
+++ b/Linux-PAM/modules/pammodutil/modutil_getpwnam.c
@@ -1,5 +1,5 @@
/*
- * $Id: modutil_getpwnam.c,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: modutil_getpwnam.c,v 1.4 2005/03/30 14:59:41 kukuk Exp $
*
* This function provides a thread safer version of getpwnam() for use
* with PAM modules that care about this sort of thing.
@@ -9,9 +9,33 @@
#include "pammodutil.h"
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
#include <pwd.h>
+#include <stdio.h>
#include <stdlib.h>
+static pthread_mutex_t _pammodutil_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void _pammodutil_lock(void)
+{
+ pthread_mutex_lock(&_pammodutil_mutex);
+}
+static void _pammodutil_unlock(void)
+{
+ pthread_mutex_unlock(&_pammodutil_mutex);
+}
+
+static int intlen(int number)
+{
+ int len = 2;
+ while (number != 0) {
+ number /= 10;
+ len++;
+ }
+ return len;
+}
+
struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user)
{
#ifdef HAVE_GETPWNAM_R
@@ -38,12 +62,44 @@ struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user)
buffer = new_buffer;
/* make the re-entrant call to get the pwd structure */
+ errno = 0;
status = getpwnam_r(user, buffer,
sizeof(struct passwd) + (char *) buffer,
length, &result);
- if (!status && result) {
- status = pam_set_data(pamh, "_pammodutil_getpwnam", result,
- _pammodutil_cleanup);
+ if (!status && (result == buffer)) {
+ char *data_name;
+ const void *ignore;
+ int i;
+
+ data_name = malloc(strlen("_pammodutil_getpwnam") + 1 +
+ strlen(user) + 1 + intlen(INT_MAX) + 1);
+ if ((pamh != NULL) && (data_name == NULL)) {
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+ free(buffer);
+ return NULL;
+ }
+
+ if (pamh != NULL) {
+ for (i = 0; i < INT_MAX; i++) {
+ sprintf(data_name, "_pammodutil_getpwnam_%s_%d", user, i);
+ _pammodutil_lock();
+ status = PAM_NO_MODULE_DATA;
+ if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
+ status = pam_set_data(pamh, data_name,
+ result, _pammodutil_cleanup);
+ }
+ _pammodutil_unlock();
+ if (status == PAM_SUCCESS) {
+ break;
+ }
+ }
+ } else {
+ status = PAM_SUCCESS;
+ }
+
+ free(data_name);
+
if (status == PAM_SUCCESS) {
D(("success"));
return result;
@@ -55,9 +111,12 @@ struct passwd *_pammodutil_getpwnam(pam_handle_t *pamh, const char *user)
free(buffer);
return NULL;
- }
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
- length <<= 1;
+ length <<= 2;
} while (length < PWD_ABSURD_PWD_LENGTH);
diff --git a/Linux-PAM/modules/pammodutil/modutil_getpwuid.c b/Linux-PAM/modules/pammodutil/modutil_getpwuid.c
index cd93ded4..8ba20d17 100644
--- a/Linux-PAM/modules/pammodutil/modutil_getpwuid.c
+++ b/Linux-PAM/modules/pammodutil/modutil_getpwuid.c
@@ -1,5 +1,5 @@
/*
- * $Id: modutil_getpwuid.c,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: modutil_getpwuid.c,v 1.4 2005/03/30 14:59:41 kukuk Exp $
*
* This function provides a thread safer version of getpwuid() for use
* with PAM modules that care about this sort of thing.
@@ -9,12 +9,46 @@
#include "pammodutil.h"
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
#include <pwd.h>
+#include <stdio.h>
#include <stdlib.h>
+static pthread_mutex_t _pammodutil_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void _pammodutil_lock(void)
+{
+ pthread_mutex_lock(&_pammodutil_mutex);
+}
+static void _pammodutil_unlock(void)
+{
+ pthread_mutex_unlock(&_pammodutil_mutex);
+}
+
+static int intlen(int number)
+{
+ int len = 2;
+ while (number != 0) {
+ number /= 10;
+ len++;
+ }
+ return len;
+}
+
+static int longlen(long number)
+{
+ int len = 2;
+ while (number != 0) {
+ number /= 10;
+ len++;
+ }
+ return len;
+}
+
struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid)
{
-#ifdef HAVE_GETPWNAM_R
+#ifdef HAVE_GETPWUID_R
void *buffer=NULL;
size_t length = PWD_INITIAL_LENGTH;
@@ -38,12 +72,45 @@ struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid)
buffer = new_buffer;
/* make the re-entrant call to get the pwd structure */
+ errno = 0;
status = getpwuid_r(uid, buffer,
sizeof(struct passwd) + (char *) buffer,
length, &result);
- if (!status && result) {
- status = pam_set_data(pamh, "_pammodutil_getpwuid", result,
- _pammodutil_cleanup);
+ if (!status && (result == buffer)) {
+ char *data_name;
+ const void *ignore;
+ int i;
+
+ data_name = malloc(strlen("_pammodutil_getpwuid") + 1 +
+ longlen((long) uid) + 1 + intlen(INT_MAX) + 1);
+ if ((pamh != NULL) && (data_name == NULL)) {
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+ free(buffer);
+ return NULL;
+ }
+
+ if (pamh != NULL) {
+ for (i = 0; i < INT_MAX; i++) {
+ sprintf(data_name, "_pammodutil_getpwuid_%ld_%d",
+ (long) uid, i);
+ _pammodutil_lock();
+ status = PAM_NO_MODULE_DATA;
+ if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
+ status = pam_set_data(pamh, data_name,
+ result, _pammodutil_cleanup);
+ }
+ _pammodutil_unlock();
+ if (status == PAM_SUCCESS) {
+ break;
+ }
+ }
+ } else {
+ status = PAM_SUCCESS;
+ }
+
+ free(data_name);
+
if (status == PAM_SUCCESS) {
D(("success"));
return result;
@@ -55,9 +122,12 @@ struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid)
free(buffer);
return NULL;
- }
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
- length <<= 1;
+ length <<= 2;
} while (length < PWD_ABSURD_PWD_LENGTH);
@@ -67,14 +137,14 @@ struct passwd *_pammodutil_getpwuid(pam_handle_t *pamh, uid_t uid)
free(buffer);
return NULL;
-#else /* ie. ifndef HAVE_GETPWNAM_R */
+#else /* ie. ifndef HAVE_GETPWUID_R */
/*
* Sorry, there does not appear to be a reentrant version of
- * getpwnam(). So, we use the standard libc function.
+ * getpwuid(). So, we use the standard libc function.
*/
return getpwuid(uid);
-#endif /* def HAVE_GETPWNAM_R */
+#endif /* def HAVE_GETPWUID_R */
}
diff --git a/Linux-PAM/modules/pammodutil/modutil_getspnam.c b/Linux-PAM/modules/pammodutil/modutil_getspnam.c
new file mode 100644
index 00000000..e966bb52
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_getspnam.c
@@ -0,0 +1,139 @@
+/*
+ * $Id: modutil_getspnam.c,v 1.3 2005/03/30 14:59:41 kukuk Exp $
+ *
+ * This function provides a thread safer version of getspnam() for use
+ * with PAM modules that care about this sort of thing.
+ *
+ * XXX - or at least it should provide a thread-safe alternative.
+ */
+
+#include "pammodutil.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <pthread.h>
+#include <shadow.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static pthread_mutex_t _pammodutil_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void _pammodutil_lock(void)
+{
+ pthread_mutex_lock(&_pammodutil_mutex);
+}
+static void _pammodutil_unlock(void)
+{
+ pthread_mutex_unlock(&_pammodutil_mutex);
+}
+
+static int intlen(int number)
+{
+ int len = 2;
+ while (number != 0) {
+ number /= 10;
+ len++;
+ }
+ return len;
+}
+
+struct spwd *_pammodutil_getspnam(pam_handle_t *pamh, const char *user)
+{
+#ifdef HAVE_GETSPNAM_R
+
+ void *buffer=NULL;
+ size_t length = PWD_INITIAL_LENGTH;
+
+ do {
+ int status;
+ void *new_buffer;
+ struct spwd *result = NULL;
+
+ new_buffer = realloc(buffer, sizeof(struct spwd) + length);
+ if (new_buffer == NULL) {
+
+ D(("out of memory"));
+
+ /* no memory for the user - so delete the memory */
+ if (buffer) {
+ free(buffer);
+ }
+ return NULL;
+ }
+ buffer = new_buffer;
+
+ /* make the re-entrant call to get the spwd structure */
+ errno = 0;
+ status = getspnam_r(user, buffer,
+ sizeof(struct spwd) + (char *) buffer,
+ length, &result);
+ if (!status && (result == buffer)) {
+ char *data_name;
+ const void *ignore;
+ int i;
+
+ data_name = malloc(strlen("_pammodutil_getspnam") + 1 +
+ strlen(user) + 1 + intlen(INT_MAX) + 1);
+ if ((pamh != NULL) && (data_name == NULL)) {
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+ free(buffer);
+ return NULL;
+ }
+
+ if (pamh != NULL) {
+ for (i = 0; i < INT_MAX; i++) {
+ sprintf(data_name, "_pammodutil_getspnam_%s_%d", user, i);
+ _pammodutil_lock();
+ status = PAM_NO_MODULE_DATA;
+ if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
+ status = pam_set_data(pamh, data_name,
+ result, _pammodutil_cleanup);
+ }
+ _pammodutil_unlock();
+ if (status == PAM_SUCCESS) {
+ break;
+ }
+ }
+ } else {
+ status = PAM_SUCCESS;
+ }
+
+ free(data_name);
+
+ if (status == PAM_SUCCESS) {
+ D(("success"));
+ return result;
+ }
+
+ D(("was unable to register the data item [%s]",
+ pam_strerror(pamh, status)));
+
+ free(buffer);
+ return NULL;
+
+ } else if (errno != ERANGE && errno != EINTR) {
+ /* no sense in repeating the call */
+ break;
+ }
+
+ length <<= 2;
+
+ } while (length < PWD_ABSURD_PWD_LENGTH);
+
+ D(("spwd structure took %u bytes or so of memory",
+ length+sizeof(struct spwd)));
+
+ free(buffer);
+ return NULL;
+
+#else /* ie. ifndef HAVE_GETSPNAM_R */
+
+ /*
+ * Sorry, there does not appear to be a reentrant version of
+ * getspnam(). So, we use the standard libc function.
+ */
+
+ return getspnam(user);
+
+#endif /* def HAVE_GETSPNAM_R */
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_ingroup.c b/Linux-PAM/modules/pammodutil/modutil_ingroup.c
new file mode 100644
index 00000000..e1f88b81
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_ingroup.c
@@ -0,0 +1,121 @@
+/*
+ * $Id: modutil_ingroup.c,v 1.1 2004/09/24 13:14:14 kukuk Exp $
+ *
+ * This function provides common methods for checking if a user is in a
+ * specified group.
+ */
+
+#include "pammodutil.h"
+#include "include/security/_pam_modutil.h"
+#include <pwd.h>
+#include <grp.h>
+
+#ifdef HAVE_GETGROUPLIST
+static int checkgrouplist(const char *user, gid_t primary, gid_t target)
+{
+ gid_t *grouplist = NULL;
+ int agroups, ngroups, i;
+ ngroups = agroups = 3;
+ do {
+ grouplist = malloc(sizeof(gid_t) * agroups);
+ if (grouplist == NULL) {
+ return 0;
+ }
+ ngroups = agroups;
+ i = getgrouplist(user, primary, grouplist, &ngroups);
+ if ((i < 0) || (ngroups < 1)) {
+ agroups *= 2;
+ free(grouplist);
+ } else {
+ for (i = 0; i < ngroups; i++) {
+ if (grouplist[i] == target) {
+ free(grouplist);
+ return 1;
+ }
+ }
+ free(grouplist);
+ }
+ } while (((i < 0) || (ngroups < 1)) && (agroups < 10000));
+ return 0;
+}
+#endif
+
+static int _pammodutil_user_in_group_common(pam_handle_t *pamh,
+ struct passwd *pwd,
+ struct group *grp)
+{
+ int i;
+
+ if (pwd == NULL) {
+ return 0;
+ }
+ if (grp == NULL) {
+ return 0;
+ }
+
+ if (pwd->pw_gid == grp->gr_gid) {
+ return 1;
+ }
+
+ for (i = 0; (grp->gr_mem != NULL) && (grp->gr_mem[i] != NULL); i++) {
+ if (strcmp(pwd->pw_name, grp->gr_mem[i]) == 0) {
+ return 1;
+ }
+ }
+
+#ifdef HAVE_GETGROUPLIST
+ if (checkgrouplist(pwd->pw_name, pwd->pw_gid, grp->gr_gid)) {
+ return 1;
+ }
+#endif
+
+ return 0;
+}
+
+int _pammodutil_user_in_group_nam_nam(pam_handle_t *pamh,
+ const char *user, const char *group)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = _pammodutil_getpwnam(pamh, user);
+ grp = _pammodutil_getgrnam(pamh, group);
+
+ return _pammodutil_user_in_group_common(pamh, pwd, grp);
+}
+
+int _pammodutil_user_in_group_nam_gid(pam_handle_t *pamh,
+ const char *user, gid_t group)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = _pammodutil_getpwnam(pamh, user);
+ grp = _pammodutil_getgrgid(pamh, group);
+
+ return _pammodutil_user_in_group_common(pamh, pwd, grp);
+}
+
+int _pammodutil_user_in_group_uid_nam(pam_handle_t *pamh,
+ uid_t user, const char *group)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = _pammodutil_getpwuid(pamh, user);
+ grp = _pammodutil_getgrnam(pamh, group);
+
+ return _pammodutil_user_in_group_common(pamh, pwd, grp);
+}
+
+int _pammodutil_user_in_group_uid_gid(pam_handle_t *pamh,
+ uid_t user, gid_t group)
+{
+ struct passwd *pwd;
+ struct group *grp;
+
+ pwd = _pammodutil_getpwuid(pamh, user);
+ grp = _pammodutil_getgrgid(pamh, group);
+
+ return _pammodutil_user_in_group_common(pamh, pwd, grp);
+}
diff --git a/Linux-PAM/modules/pammodutil/modutil_ioloop.c b/Linux-PAM/modules/pammodutil/modutil_ioloop.c
new file mode 100644
index 00000000..37ac76fc
--- /dev/null
+++ b/Linux-PAM/modules/pammodutil/modutil_ioloop.c
@@ -0,0 +1,52 @@
+/*
+ * $Id: modutil_ioloop.c,v 1.2 2004/09/24 09:18:22 kukuk Exp $
+ *
+ * These functions provides common methods for ensure a complete read or
+ * write occurs. It handles EINTR and partial read/write returns.
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <security/pam_modules.h>
+#include "include/security/_pam_modutil.h"
+
+int _pammodutil_read(int fd, char *buffer, int count)
+{
+ int block, offset = 0;
+
+ while (count > 0) {
+ block = read(fd, &buffer[offset], count);
+
+ if (block < 0) {
+ if (errno == EINTR) continue;
+ return block;
+ }
+ if (block == 0) return offset;
+
+ offset += block;
+ count -= block;
+ }
+
+ return offset;
+}
+
+int _pammodutil_write(int fd, const char *buffer, int count)
+{
+ int block, offset = 0;
+
+ while (count > 0) {
+ block = write(fd, &buffer[offset], count);
+
+ if (block < 0) {
+ if (errno == EINTR) continue;
+ return block;
+ }
+ if (block == 0) return offset;
+
+ offset += block;
+ count -= block;
+ }
+
+ return offset;
+}
diff --git a/Linux-PAM/modules/pammodutil/pammodutil.h b/Linux-PAM/modules/pammodutil/pammodutil.h
index 78d7e517..2b80c852 100644
--- a/Linux-PAM/modules/pammodutil/pammodutil.h
+++ b/Linux-PAM/modules/pammodutil/pammodutil.h
@@ -2,7 +2,7 @@
#define PAMMODUTIL_H
/*
- * $Id: pammodutil.h,v 1.1.1.1 2002/09/15 20:09:04 hartmans Exp $
+ * $Id: pammodutil.h,v 1.2 2005/03/30 10:42:54 t8m Exp $
*
* Copyright (c) 2001 Andrew Morgan <morgan@kernel.org>
*/
@@ -13,7 +13,7 @@
#include <security/_pam_modutil.h>
#define PWD_INITIAL_LENGTH 0x100
-#define PWD_ABSURD_PWD_LENGTH 0x1000
+#define PWD_ABSURD_PWD_LENGTH 0x8000
/* This is a simple cleanup, it just free()s the 'data' memory */
extern void _pammodutil_cleanup(pam_handle_t *pamh, void *data,