Signed-off-by: Nikos Mavrogiannopoulos <nmav@gnutls.org>lilik-openwrt-22.03
@ -0,0 +1,71 @@ | |||
# | |||
# Copyright (C) 2006-2014 OpenWrt.org | |||
# | |||
# This is free software, licensed under the GNU General Public License v2. | |||
# See /LICENSE for more information. | |||
# | |||
include $(TOPDIR)/rules.mk | |||
PKG_NAME:=libpam | |||
PKG_VERSION:=1.1.8 | |||
PKG_RELEASE:=3 | |||
PKG_SOURCE:=Linux-PAM-$(PKG_VERSION).tar.bz2 | |||
PKG_SOURCE_URL:=http://www.linux-pam.org/library/ | |||
PKG_MD5SUM:=35b6091af95981b1b2cd60d813b5e4ee | |||
PKG_INSTALL:=1 | |||
PKG_FIXUP:=autoreconf | |||
PKG_MAINTAINER:=Nikos Mavrogiannopoulos <n.mavrogiannopoulos@gmail.com> | |||
PKG_BUILD_DIR:=$(BUILD_DIR)/Linux-PAM-$(PKG_VERSION) | |||
include $(INCLUDE_DIR)/package.mk | |||
define Package/libpam | |||
SECTION:=libs | |||
CATEGORY:=Libraries | |||
TITLE:=the Linux-PAM libraries and modules. | |||
URL:=http://www.kernel.org/pub/linux/libs/pam | |||
endef | |||
define Package/libpam/description | |||
The Linux-PAM Pluggable Authentication Modules. | |||
endef | |||
TARGET_CFLAGS += $(FPIC) | |||
define Build/Configure | |||
$(call Build/Configure/Default, \ | |||
--enable-shared \ | |||
--enable-static \ | |||
--enable-pamlocking \ | |||
--disable-prelude \ | |||
--disable-lckpwdf \ | |||
--disable-selinux \ | |||
--disable-nls \ | |||
--disable-rpath \ | |||
--enable-db=no \ | |||
) | |||
endef | |||
define Build/InstallDev | |||
$(INSTALL_DIR) $(1)/lib | |||
$(INSTALL_DIR) $(1)/usr/include | |||
$(CP) $(PKG_INSTALL_DIR)/lib/* $(1)/lib/ | |||
$(CP) $(PKG_INSTALL_DIR)/usr/include/* $(1)/usr/include | |||
endef | |||
define Package/libpam/install | |||
$(INSTALL_DIR) $(1)/lib $(1)/lib/security $(1)/lib/security/pam_filter | |||
$(INSTALL_DIR) $(1)/etc $(1)/etc/pam.d | |||
$(INSTALL_DIR) $(1)/usr/sbin | |||
$(CP) $(PKG_INSTALL_DIR)/lib/*.so* $(1)/lib/ | |||
$(CP) $(PKG_INSTALL_DIR)/lib/security/*.so* $(1)/lib/security/ | |||
$(CP) $(PKG_INSTALL_DIR)/lib/security/pam_filter/* $(1)/lib/security/pam_filter/ | |||
$(CP) $(PKG_INSTALL_DIR)/etc/* $(1)/etc/ | |||
$(CP) ./files/* $(1)/etc/ | |||
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/* $(1)/usr/sbin/ | |||
endef | |||
$(eval $(call BuildPackage,libpam)) |
@ -0,0 +1,15 @@ | |||
# ---------------------------------------------------------------------------# | |||
# /etc/pam.conf # | |||
# ---------------------------------------------------------------------------# | |||
# | |||
# NOTE | |||
# ---- | |||
# | |||
# NOTE: Most program use a file under the /etc/pam.d/ directory to setup their | |||
# PAM service modules. This file is used only if that directory does not exist. | |||
# ---------------------------------------------------------------------------# | |||
# Format: | |||
# serv. module ctrl module [path] ...[args..] # | |||
# name type flag # | |||
@ -0,0 +1,20 @@ | |||
# | |||
# /etc/pam.d/common-account - authorization settings common to all services | |||
# | |||
# This file is included from other service-specific PAM config files, | |||
# and should contain a list of the authorization modules that define | |||
# the central access policy for use on the system. The default is to | |||
# only deny service to users whose accounts are expired in /etc/shadow. | |||
# | |||
# here are the per-package modules (the "Primary" block) | |||
account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so | |||
# here's the fallback if no module succeeds | |||
account requisite pam_deny.so | |||
# prime the stack with a positive return value if there isn't one already; | |||
# this avoids us returning an error just because nothing sets a success code | |||
# since the modules above will each just jump around | |||
account required pam_permit.so | |||
# and here are more per-package modules (the "Additional" block) | |||
# end of pam-auth-update config |
@ -0,0 +1,21 @@ | |||
# | |||
# /etc/pam.d/common-auth - authentication settings common to all services | |||
# | |||
# This file is included from other service-specific PAM config files, | |||
# and should contain a list of the authentication modules that define | |||
# the central authentication scheme for use on the system | |||
# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the | |||
# traditional Unix authentication mechanisms. | |||
# | |||
# here are the per-package modules (the "Primary" block) | |||
auth [success=1 default=ignore] pam_unix.so nullok_secure | |||
# here's the fallback if no module succeeds | |||
auth requisite pam_deny.so | |||
# prime the stack with a positive return value if there isn't one already; | |||
# this avoids us returning an error just because nothing sets a success code | |||
# since the modules above will each just jump around | |||
auth required pam_permit.so | |||
# and here are more per-package modules (the "Additional" block) | |||
# end of pam-auth-update config |
@ -0,0 +1,28 @@ | |||
# | |||
# /etc/pam.d/common-password - password-related modules common to all services | |||
# | |||
# This file is included from other service-specific PAM config files, | |||
# and should contain a list of modules that define the services to be | |||
# used to change user passwords. The default is pam_unix. | |||
# Explanation of pam_unix options: | |||
# | |||
# The "sha512" option enables salted SHA512 passwords. Without this option, | |||
# the default is Unix crypt. Prior releases used the option "md5". | |||
# | |||
# The "obscure" option replaces the old `OBSCURE_CHECKS_ENAB' option in | |||
# login.defs. | |||
# | |||
# See the pam_unix manpage for other options. | |||
# here are the per-package modules (the "Primary" block) | |||
password [success=1 default=ignore] pam_unix.so obscure sha512 | |||
# here's the fallback if no module succeeds | |||
password requisite pam_deny.so | |||
# prime the stack with a positive return value if there isn't one already; | |||
# this avoids us returning an error just because nothing sets a success code | |||
# since the modules above will each just jump around | |||
password required pam_permit.so | |||
# and here are more per-package modules (the "Additional" block) | |||
# end of pam-auth-update config |
@ -0,0 +1,25 @@ | |||
# | |||
# /etc/pam.d/common-session - session-related modules common to all services | |||
# | |||
# This file is included from other service-specific PAM config files, | |||
# and should contain a list of modules that define tasks to be performed | |||
# at the start and end of sessions of *any* kind (both interactive and | |||
# non-interactive). | |||
# | |||
# here are the per-package modules (the "Primary" block) | |||
session [default=1] pam_permit.so | |||
# here's the fallback if no module succeeds | |||
session requisite pam_deny.so | |||
# prime the stack with a positive return value if there isn't one already; | |||
# this avoids us returning an error just because nothing sets a success code | |||
# since the modules above will each just jump around | |||
session required pam_permit.so | |||
# The pam_umask module will set the umask according to the system default in | |||
# /etc/login.defs and user settings, solving the problem of different | |||
# umask settings with different shells, display managers, remote sessions etc. | |||
# See "man pam_umask". | |||
session optional pam_umask.so | |||
# and here are more per-package modules (the "Additional" block) | |||
session required pam_unix.so | |||
# end of pam-auth-update config |
@ -0,0 +1,25 @@ | |||
# | |||
# /etc/pam.d/common-session-noninteractive - session-related modules | |||
# common to all non-interactive services | |||
# | |||
# This file is included from other service-specific PAM config files, | |||
# and should contain a list of modules that define tasks to be performed | |||
# at the start and end of all non-interactive sessions. | |||
# | |||
# here are the per-package modules (the "Primary" block) | |||
session [default=1] pam_permit.so | |||
# here's the fallback if no module succeeds | |||
session requisite pam_deny.so | |||
# prime the stack with a positive return value if there isn't one already; | |||
# this avoids us returning an error just because nothing sets a success code | |||
# since the modules above will each just jump around | |||
session required pam_permit.so | |||
# The pam_umask module will set the umask according to the system default in | |||
# /etc/login.defs and user settings, solving the problem of different | |||
# umask settings with different shells, display managers, remote sessions etc. | |||
# See "man pam_umask". | |||
session optional pam_umask.so | |||
# and here are more per-package modules (the "Additional" block) | |||
session required pam_unix.so | |||
# end of pam-auth-update config |
@ -0,0 +1,16 @@ | |||
# | |||
# /etc/pam.d/other - specify the PAM fallback behaviour | |||
# | |||
# Note that this file is used for any unspecified service; for example | |||
#if /etc/pam.d/cron specifies no session modules but cron calls | |||
#pam_open_session, the session module out of /etc/pam.d/other is | |||
#used. If you really want nothing to happen then use pam_permit.so or | |||
#pam_deny.so as appropriate. | |||
# We fall back to the system default in /etc/pam.d/common-* | |||
# | |||
auth include common-auth | |||
account include common-account | |||
password include common-password | |||
session include common-session |
@ -0,0 +1,35 @@ | |||
This patch is used to create a new sub package libpam-xtests to do more checks. | |||
Upstream-Status: Pending | |||
Signed-off-by: Kang Kai <kai.kang@windriver.com> | |||
--- a/xtests/Makefile.am | |||
+++ b/xtests/Makefile.am | |||
@@ -7,7 +7,7 @@ AM_CFLAGS = -DLIBPAM_COMPILE -I$(top_src | |||
LDADD = $(top_builddir)/libpam/libpam.la \ | |||
$(top_builddir)/libpam_misc/libpam_misc.la | |||
-CLEANFILES = *~ $(XTESTS) | |||
+CLEANFILES = *~ | |||
EXTRA_DIST = run-xtests.sh tst-pam_dispatch1.pamd tst-pam_dispatch2.pamd \ | |||
tst-pam_dispatch3.pamd tst-pam_dispatch4.pamd \ | |||
@@ -51,3 +51,18 @@ EXTRA_PROGRAMS = $(XTESTS) | |||
xtests: $(XTESTS) run-xtests.sh | |||
"$(srcdir)"/run-xtests.sh "$(srcdir)" ${XTESTS} ${NOSRCTESTS} | |||
+ | |||
+all: $(XTESTS) | |||
+ | |||
+install: install_xtests | |||
+ | |||
+install_xtests: | |||
+ $(INSTALL) -d $(DESTDIR)$(pkgdatadir)/xtests | |||
+ for file in $(EXTRA_DIST) ; do \ | |||
+ $(INSTALL) $$file $(DESTDIR)$(pkgdatadir)/xtests ; \ | |||
+ done | |||
+ for file in $(XTESTS); do \ | |||
+ $(INSTALL) .libs/$$file $(DESTDIR)$(pkgdatadir)/xtests ; \ | |||
+ done | |||
+ | |||
+.PHONY: all install_xtests |
@ -0,0 +1,85 @@ | |||
innetgr may not be there so make sure that when innetgr is not present | |||
then we inform about it and not use it. | |||
-Khem | |||
--- a/modules/pam_group/pam_group.c | |||
+++ b/modules/pam_group/pam_group.c | |||
@@ -656,7 +656,11 @@ static int check_account(pam_handle_t *p | |||
} | |||
/* If buffer starts with @, we are using netgroups */ | |||
if (buffer[0] == '@') | |||
+#ifdef HAVE_INNETGR | |||
good &= innetgr (&buffer[1], NULL, user, NULL); | |||
+#else | |||
+ pam_syslog (pamh, LOG_ERR, "pam_group does not have netgroup support"); | |||
+#endif | |||
/* otherwise, if the buffer starts with %, it's a UNIX group */ | |||
else if (buffer[0] == '%') | |||
good &= pam_modutil_user_in_group_nam_nam(pamh, user, &buffer[1]); | |||
--- a/modules/pam_time/pam_time.c | |||
+++ b/modules/pam_time/pam_time.c | |||
@@ -555,9 +555,13 @@ check_account(pam_handle_t *pamh, const | |||
} | |||
/* If buffer starts with @, we are using netgroups */ | |||
if (buffer[0] == '@') | |||
- good &= innetgr (&buffer[1], NULL, user, NULL); | |||
+#ifdef HAVE_INNETGR | |||
+ good &= innetgr (&buffer[1], NULL, user, NULL); | |||
+#else | |||
+ pam_syslog (pamh, LOG_ERR, "pam_time does not have netgroup support"); | |||
+#endif | |||
else | |||
- good &= logic_field(pamh, user, buffer, count, is_same); | |||
+ good &= logic_field(pamh, user, buffer, count, is_same); | |||
D(("with user: %s", good ? "passes":"fails" )); | |||
/* here we get the time field */ | |||
--- a/modules/pam_succeed_if/pam_succeed_if.c | |||
+++ b/modules/pam_succeed_if/pam_succeed_if.c | |||
@@ -231,18 +231,27 @@ evaluate_notingroup(pam_handle_t *pamh, | |||
} | |||
/* Return PAM_SUCCESS if the (host,user) is in the netgroup. */ | |||
static int | |||
-evaluate_innetgr(const char *host, const char *user, const char *group) | |||
+evaluate_innetgr(const pam_handle_t* pamh, const char *host, const char *user, const char *group) | |||
{ | |||
+#ifdef HAVE_INNETGR | |||
if (innetgr(group, host, user, NULL) == 1) | |||
return PAM_SUCCESS; | |||
+#else | |||
+ pam_syslog (pamh, LOG_ERR, "pam_succeed_if does not have netgroup support"); | |||
+#endif | |||
+ | |||
return PAM_AUTH_ERR; | |||
} | |||
/* Return PAM_SUCCESS if the (host,user) is NOT in the netgroup. */ | |||
static int | |||
-evaluate_notinnetgr(const char *host, const char *user, const char *group) | |||
+evaluate_notinnetgr(const pam_handle_t* pamh, const char *host, const char *user, const char *group) | |||
{ | |||
+#ifdef HAVE_INNETGR | |||
if (innetgr(group, host, user, NULL) == 0) | |||
return PAM_SUCCESS; | |||
+#else | |||
+ pam_syslog (pamh, LOG_ERR, "pam_succeed_if does not have netgroup support"); | |||
+#endif | |||
return PAM_AUTH_ERR; | |||
} | |||
@@ -387,14 +396,14 @@ evaluate(pam_handle_t *pamh, int debug, | |||
const void *rhost; | |||
if (pam_get_item(pamh, PAM_RHOST, &rhost) != PAM_SUCCESS) | |||
rhost = NULL; | |||
- return evaluate_innetgr(rhost, user, right); | |||
+ return evaluate_innetgr(pamh, rhost, user, right); | |||
} | |||
/* (Rhost, user) is not in this group. */ | |||
if (strcasecmp(qual, "notinnetgr") == 0) { | |||
const void *rhost; | |||
if (pam_get_item(pamh, PAM_RHOST, &rhost) != PAM_SUCCESS) | |||
rhost = NULL; | |||
- return evaluate_notinnetgr(rhost, user, right); | |||
+ return evaluate_notinnetgr(pamh, rhost, user, right); | |||
} | |||
/* Fail closed. */ | |||
return PAM_SERVICE_ERR; |
@ -0,0 +1,68 @@ | |||
--- a/modules/pam_access/pam_access.c | |||
+++ b/modules/pam_access/pam_access.c | |||
@@ -44,7 +44,7 @@ | |||
#include <arpa/inet.h> | |||
#include <netdb.h> | |||
#include <sys/socket.h> | |||
-#ifdef HAVE_RPCSVC_YPCLNT_H | |||
+#ifdef HAVE_RPCSVC_YPCLNT_H && USE_NIS | |||
#include <rpcsvc/ypclnt.h> | |||
#endif | |||
#ifdef HAVE_LIBAUDIT | |||
--- a/modules/pam_unix/pam_unix_passwd.c | |||
+++ b/modules/pam_unix/pam_unix_passwd.c | |||
@@ -79,18 +79,18 @@ | |||
#include "passverify.h" | |||
#include "bigcrypt.h" | |||
-#if (HAVE_YP_GET_DEFAULT_DOMAIN || HAVE_GETDOMAINNAME) && HAVE_YP_MASTER | |||
+#if (HAVE_YP_GET_DEFAULT_DOMAIN || HAVE_GETDOMAINNAME) && HAVE_YP_MASTER && USE_NIS | |||
# define HAVE_NIS | |||
#endif | |||
#ifdef HAVE_NIS | |||
# include <rpc/rpc.h> | |||
-# if HAVE_RPCSVC_YP_PROT_H | |||
+# if HAVE_RPCSVC_YP_PROT_H && USE_NIS | |||
# include <rpcsvc/yp_prot.h> | |||
# endif | |||
-# if HAVE_RPCSVC_YPCLNT_H | |||
+# if HAVE_RPCSVC_YPCLNT_H && USE_NIS | |||
# include <rpcsvc/ypclnt.h> | |||
# endif | |||
--- a/modules/pam_unix/support.c | |||
+++ b/modules/pam_unix/support.c | |||
@@ -19,7 +19,7 @@ | |||
#include <ctype.h> | |||
#include <syslog.h> | |||
#include <sys/resource.h> | |||
-#ifdef HAVE_RPCSVC_YPCLNT_H | |||
+#ifdef HAVE_RPCSVC_YPCLNT_H && USE_NIS | |||
#include <rpcsvc/ypclnt.h> | |||
#endif | |||
@@ -402,7 +402,7 @@ int _unix_getpwnam(pam_handle_t *pamh, c | |||
} | |||
} | |||
-#if defined(HAVE_YP_GET_DEFAULT_DOMAIN) && defined (HAVE_YP_BIND) && defined (HAVE_YP_MATCH) && defined (HAVE_YP_UNBIND) | |||
+#if defined(HAVE_YP_GET_DEFAULT_DOMAIN) && defined (HAVE_YP_BIND) && defined (HAVE_YP_MATCH) && defined (HAVE_YP_UNBIND) && (USE_NIS) | |||
if (!matched && nis) { | |||
char *userinfo = NULL, *domain = NULL; | |||
int len = 0, i; | |||
--- a/modules/pam_unix/yppasswd_xdr.c | |||
+++ b/modules/pam_unix/yppasswd_xdr.c | |||
@@ -15,6 +15,10 @@ | |||
#ifdef HAVE_RPC_RPC_H | |||
#include <rpc/rpc.h> | |||
+#ifdef USE_NIS | |||
+#include <rpcsvc/yp_prot.h> | |||
+#include <rpcsvc/ypclnt.h> | |||
+#endif | |||
#include "yppasswd.h" | |||
bool_t |
@ -0,0 +1,26 @@ | |||
--- a/conf/pam_conv1/pam_conv_l.c | |||
+++ b/conf/pam_conv1/pam_conv_l.c | |||
@@ -534,7 +534,9 @@ void yyset_lineno (int line_number ); | |||
#ifdef __cplusplus | |||
extern "C" int yywrap (void ); | |||
#else | |||
-extern int yywrap (void ); | |||
+int yywrap (void ) { | |||
+ return 1; | |||
+} | |||
#endif | |||
#endif | |||
--- a/doc/specs/parse_l.c | |||
+++ b/doc/specs/parse_l.c | |||
@@ -520,7 +520,9 @@ void yyset_lineno (int line_number ); | |||
#ifdef __cplusplus | |||
extern "C" int yywrap (void ); | |||
#else | |||
-extern int yywrap (void ); | |||
+int yywrap (void ) { | |||
+ return 1; | |||
+} | |||
#endif | |||
#endif | |||
@ -0,0 +1,22 @@ | |||
--- a/Makefile.am | |||
+++ b/Makefile.am | |||
@@ -4,7 +4,7 @@ | |||
AUTOMAKE_OPTIONS = 1.9 gnu dist-bzip2 check-news | |||
-SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc examples xtests | |||
+SUBDIRS = libpam tests libpamc libpam_misc modules po conf examples xtests | |||
CLEANFILES = *~ | |||
--- a/Makefile.in | |||
+++ b/Makefile.in | |||
@@ -288,7 +288,7 @@ top_build_prefix = @top_build_prefix@ | |||
top_builddir = @top_builddir@ | |||
top_srcdir = @top_srcdir@ | |||
AUTOMAKE_OPTIONS = 1.9 gnu dist-bzip2 check-news | |||
-SUBDIRS = libpam tests libpamc libpam_misc modules po conf doc examples xtests | |||
+SUBDIRS = libpam tests libpamc libpam_misc modules po conf examples xtests | |||
CLEANFILES = *~ | |||
EXTRA_DIST = pgp.keys.asc CHANGELOG ChangeLog-CVS Copyright Make.xml.rules | |||
ACLOCAL_AMFLAGS = -I m4 |
@ -0,0 +1,16 @@ | |||
--- a/configure.in | |||
+++ b/configure.in | |||
@@ -28,12 +28,7 @@ dnl If we use /usr as prefix, use /etc f | |||
fi | |||
if test ${libdir} = '${exec_prefix}/lib' | |||
then | |||
- case "`uname -m`" in | |||
- x86_64|ppc64|s390x|sparc64) | |||
- libdir="/lib64" ;; | |||
- *) | |||
- libdir="/lib" ;; | |||
- esac | |||
+ libdir="/lib" | |||
fi | |||
if test ${sbindir} = '${exec_prefix}/sbin' | |||
then |
@ -0,0 +1,364 @@ | |||
--- a/modules/pam_rhosts/pam_rhosts.c | |||
+++ b/modules/pam_rhosts/pam_rhosts.c | |||
@@ -43,6 +43,361 @@ | |||
#include <security/pam_modutil.h> | |||
#include <security/pam_ext.h> | |||
+#ifdef __UCLIBC__ | |||
+ | |||
+#include <stdio.h> | |||
+#include <sys/stat.h> | |||
+ | |||
+ | |||
+int __check_rhosts_file = 1; | |||
+ | |||
+/* Extremely paranoid file open function. */ | |||
+static FILE * | |||
+iruserfopen (const char *file, uid_t okuser) | |||
+{ | |||
+ struct stat st; | |||
+ char *cp = NULL; | |||
+ FILE *res = NULL; | |||
+ | |||
+ /* If not a regular file, if owned by someone other than user or | |||
+ root, if writeable by anyone but the owner, or if hardlinked | |||
+ anywhere, quit. */ | |||
+ if (lstat (file, &st)) | |||
+ cp = "lstat failed"; | |||
+ else if (!S_ISREG (st.st_mode)) | |||
+ cp = "not regular file"; | |||
+ else | |||
+ { | |||
+ res = fopen (file, "r"); | |||
+ if (!res) | |||
+ cp = "cannot open"; | |||
+ else if (fstat (fileno (res), &st) < 0) | |||
+ cp = "fstat failed"; | |||
+ else if (st.st_uid && st.st_uid != okuser) | |||
+ cp = "bad owner"; | |||
+ else if (st.st_mode & (S_IWGRP|S_IWOTH)) | |||
+ cp = "writeable by other than owner"; | |||
+ else if (st.st_nlink > 1) | |||
+ cp = "hard linked somewhere"; | |||
+ } | |||
+ | |||
+ /* If there were any problems, quit. */ | |||
+ if (cp != NULL) | |||
+ { | |||
+ if (res) | |||
+ fclose (res); | |||
+ return NULL; | |||
+ } | |||
+ | |||
+ return res; | |||
+} | |||
+ | |||
+/* | |||
+ * Returns 1 for blank lines (or only comment lines) and 0 otherwise | |||
+ */ | |||
+static int | |||
+__isempty(char *p) | |||
+{ | |||
+ while (*p && isspace (*p)) { | |||
+ ++p; | |||
+ } | |||
+ | |||
+ return (*p == '\0' || *p == '#') ? 1 : 0 ; | |||
+} | |||
+ | |||
+/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ | |||
+static int | |||
+__icheckhost (u_int32_t raddr, char *lhost, const char *rhost) | |||
+{ | |||
+ struct hostent *hp; | |||
+ u_int32_t laddr; | |||
+ int negate=1; /* Multiply return with this to get -1 instead of 1 */ | |||
+ char **pp; | |||
+ | |||
+#ifdef __UCLIBC_HAS_REENTRANT_RPC__ | |||
+ int save_errno; | |||
+ size_t buflen; | |||
+ char *buffer; | |||
+ struct hostent hostbuf; | |||
+ int herr; | |||
+#endif | |||
+ | |||
+#ifdef HAVE_NETGROUP | |||
+ /* Check nis netgroup. */ | |||
+ if (strncmp ("+@", lhost, 2) == 0) | |||
+ return innetgr (&lhost[2], rhost, NULL, NULL); | |||
+ | |||
+ if (strncmp ("-@", lhost, 2) == 0) | |||
+ return -innetgr (&lhost[2], rhost, NULL, NULL); | |||
+#endif /* HAVE_NETGROUP */ | |||
+ | |||
+ /* -host */ | |||
+ if (strncmp ("-", lhost,1) == 0) { | |||
+ negate = -1; | |||
+ lhost++; | |||
+ } else if (strcmp ("+",lhost) == 0) { | |||
+ return 1; /* asking for trouble, but ok.. */ | |||
+ } | |||
+ | |||
+ /* Try for raw ip address first. */ | |||
+ if (isdigit (*lhost) && (laddr = inet_addr (lhost)) != INADDR_NONE) | |||
+ return negate * (! (raddr ^ laddr)); | |||
+ | |||
+ /* Better be a hostname. */ | |||
+#ifdef __UCLIBC_HAS_REENTRANT_RPC__ | |||
+ buflen = 1024; | |||
+ buffer = malloc(buflen); | |||
+ save_errno = errno; | |||
+ | |||
+ while (gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr) | |||
+ != 0) { | |||
+ free(buffer); | |||
+ return (0); | |||
+ } | |||
+ free(buffer); | |||
+ __set_errno (save_errno); | |||
+#else | |||
+ hp = gethostbyname(lhost); | |||
+#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */ | |||
+ | |||
+ if (hp == NULL) | |||
+ return 0; | |||
+ | |||
+ /* Spin through ip addresses. */ | |||
+ for (pp = hp->h_addr_list; *pp; ++pp) | |||
+ if (!memcmp (&raddr, *pp, sizeof (u_int32_t))) | |||
+ return negate; | |||
+ | |||
+ /* No match. */ | |||
+ return (0); | |||
+} | |||
+ | |||
+/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ | |||
+static int | |||
+__icheckuser (const char *luser, const char *ruser) | |||
+{ | |||
+ | |||
+ /* | |||
+ luser is user entry from .rhosts/hosts.equiv file | |||
+ ruser is user id on remote host | |||
+ */ | |||
+ | |||
+#ifdef HAVE_NETGROUP | |||
+ /* [-+]@netgroup */ | |||
+ if (strncmp ("+@", luser, 2) == 0) | |||
+ return innetgr (&luser[2], NULL, ruser, NULL); | |||
+ | |||
+ if (strncmp ("-@", luser,2) == 0) | |||
+ return -innetgr (&luser[2], NULL, ruser, NULL); | |||
+#endif /* HAVE_NETGROUP */ | |||
+ | |||
+ /* -user */ | |||
+ if (strncmp ("-", luser, 1) == 0) | |||
+ return -(strcmp (&luser[1], ruser) == 0); | |||
+ | |||
+ /* + */ | |||
+ if (strcmp ("+", luser) == 0) | |||
+ return 1; | |||
+ | |||
+ /* simple string match */ | |||
+ return strcmp (ruser, luser) == 0; | |||
+} | |||
+ | |||
+/* | |||
+ * Returns 0 if positive match, -1 if _not_ ok. | |||
+ */ | |||
+static int | |||
+__ivaliduser2(FILE *hostf, u_int32_t raddr, const char *luser, | |||
+ const char *ruser, const char *rhost) | |||
+{ | |||
+ register const char *user; | |||
+ register char *p; | |||
+ int hcheck, ucheck; | |||
+ char *buf = NULL; | |||
+ size_t bufsize = 0; | |||
+ int retval = -1; | |||
+ | |||
+ while (getline (&buf, &bufsize, hostf) > 0) { | |||
+ buf[bufsize - 1] = '\0'; /* Make sure it's terminated. */ | |||
+ p = buf; | |||
+ | |||
+ /* Skip empty or comment lines */ | |||
+ if (__isempty (p)) { | |||
+ continue; | |||
+ } | |||
+ | |||
+ /* Skip lines that are too long. */ | |||
+ if (strchr (p, '\n') == NULL) { | |||
+ int ch = getc_unlocked (hostf); | |||
+ | |||
+ while (ch != '\n' && ch != EOF) | |||
+ ch = getc_unlocked (hostf); | |||
+ continue; | |||
+ } | |||
+ | |||
+ for (;*p && !isspace(*p); ++p) { | |||
+ *p = tolower (*p); | |||
+ } | |||
+ | |||
+ /* Next we want to find the permitted name for the remote user. */ | |||
+ if (*p == ' ' || *p == '\t') { | |||
+ /* <nul> terminate hostname and skip spaces */ | |||
+ for (*p++='\0'; *p && isspace (*p); ++p); | |||
+ | |||
+ user = p; /* this is the user's name */ | |||
+ while (*p && !isspace (*p)) | |||
+ ++p; /* find end of user's name */ | |||
+ } else | |||
+ user = p; | |||
+ | |||
+ *p = '\0'; /* <nul> terminate username (+host?) */ | |||
+ | |||
+ /* buf -> host(?) ; user -> username(?) */ | |||
+ | |||
+ /* First check host part */ | |||
+ hcheck = __icheckhost (raddr, buf, rhost); | |||
+ | |||
+ if (hcheck < 0) | |||
+ break; | |||
+ | |||
+ if (hcheck) { | |||
+ /* Then check user part */ | |||
+ if (! (*user)) | |||
+ user = luser; | |||
+ | |||
+ ucheck = __icheckuser (user, ruser); | |||
+ | |||
+ /* Positive 'host user' match? */ | |||
+ if (ucheck > 0) { | |||
+ retval = 0; | |||
+ break; | |||
+ } | |||
+ | |||
+ /* Negative 'host -user' match? */ | |||
+ if (ucheck < 0) | |||
+ break; | |||
+ | |||
+ /* Neither, go on looking for match */ | |||
+ } | |||
+ } | |||
+ | |||
+ free (buf); | |||
+ | |||
+ return retval; | |||
+} | |||
+ | |||
+static int | |||
+iruserok2 (u_int32_t raddr, int superuser, const char *ruser, const char *luser, | |||
+ const char *rhost) | |||
+{ | |||
+ FILE *hostf = NULL; | |||
+ int isbad = -1; | |||
+ | |||
+ if (!superuser) | |||
+ hostf = iruserfopen (_PATH_HEQUIV, 0); | |||
+ | |||
+ if (hostf) { | |||
+ isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); | |||
+ fclose (hostf); | |||
+ | |||
+ if (!isbad) | |||
+ return 0; | |||
+ } | |||
+ | |||
+ if (__check_rhosts_file || superuser) { | |||
+ char *pbuf; | |||
+ struct passwd *pwd; | |||
+ size_t dirlen; | |||
+ uid_t uid; | |||
+ | |||
+#ifdef __UCLIBC_HAS_REENTRANT_RPC__ | |||
+ size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); | |||
+ struct passwd pwdbuf; | |||
+ char *buffer = stack_heap_alloc(buflen); | |||
+ | |||
+ if (getpwnam_r (luser, &pwdbuf, buffer, | |||
+ buflen, &pwd) != 0 || pwd == NULL) | |||
+ { | |||
+ stack_heap_free(buffer); | |||
+ return -1; | |||
+ } | |||
+ stack_heap_free(buffer); | |||
+#else | |||
+ if ((pwd = getpwnam(luser)) == NULL) | |||
+ return -1; | |||
+#endif | |||
+ | |||
+ dirlen = strlen (pwd->pw_dir); | |||
+ pbuf = malloc (dirlen + sizeof "/.rhosts"); | |||
+ strcpy (pbuf, pwd->pw_dir); | |||
+ strcat (pbuf, "/.rhosts"); | |||
+ | |||
+ /* Change effective uid while reading .rhosts. If root and | |||
+ reading an NFS mounted file system, can't read files that | |||
+ are protected read/write owner only. */ | |||
+ uid = geteuid (); | |||
+ seteuid (pwd->pw_uid); | |||
+ hostf = iruserfopen (pbuf, pwd->pw_uid); | |||
+ free(pbuf); | |||
+ | |||
+ if (hostf != NULL) { | |||
+ isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); | |||
+ fclose (hostf); | |||
+ } | |||
+ | |||
+ seteuid (uid); | |||
+ return isbad; | |||
+ } | |||
+ return -1; | |||
+} | |||
+ | |||
+int ruserok(const char *rhost, int superuser, const char *ruser, | |||
+ const char *luser) | |||
+{ | |||
+ struct hostent *hp; | |||
+ u_int32_t addr; | |||
+ char **ap; | |||
+#ifdef __UCLIBC_HAS_REENTRANT_RPC__ | |||
+ size_t buflen; | |||
+ char *buffer; | |||
+ int herr; | |||
+ struct hostent hostbuf; | |||
+#endif | |||
+ | |||
+#ifdef __UCLIBC_HAS_REENTRANT_RPC__ | |||
+ buflen = 1024; | |||
+ buffer = stack_heap_alloc(buflen); | |||
+ | |||
+ while (gethostbyname_r (rhost, &hostbuf, buffer, | |||
+ buflen, &hp, &herr) != 0 || hp == NULL) | |||
+ { | |||
+ if (herr != NETDB_INTERNAL || errno != ERANGE) { | |||
+ stack_heap_free(buffer); | |||
+ return -1; | |||
+ } else | |||
+ { | |||
+ /* Enlarge the buffer. */ | |||
+ buflen *= 2; | |||
+ stack_heap_free(buffer); | |||
+ buffer = stack_heap_alloc(buflen); | |||
+ } | |||
+ } | |||
+ stack_heap_free(buffer); | |||
+#else | |||
+ if ((hp = gethostbyname(rhost)) == NULL) { | |||
+ return -1; | |||
+ } | |||
+#endif | |||
+ for (ap = hp->h_addr_list; *ap; ++ap) { | |||
+ memmove(&addr, *ap, sizeof(addr)); | |||
+ if (iruserok2(addr, superuser, ruser, luser, rhost) == 0) | |||
+ return 0; | |||
+ } | |||
+ return -1; | |||
+} | |||
+ | |||
+#endif /* __UCLIBC__ */ | |||
+ | |||
PAM_EXTERN | |||
int pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, | |||
const char **argv) |
@ -0,0 +1,271 @@ | |||
--- a/modules/pam_unix/yppasswd_xdr.c | |||
+++ b/modules/pam_unix/yppasswd_xdr.c | |||
@@ -21,6 +21,268 @@ | |||
#endif | |||
#include "yppasswd.h" | |||
+#ifdef __UCLIBC__ | |||
+ | |||
+static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0}; | |||
+ | |||
+/* | |||
+ * XDR integers | |||
+ */ | |||
+bool_t | |||
+xdr_int (XDR *xdrs, int *ip) | |||
+{ | |||
+ | |||
+#if INT_MAX < LONG_MAX | |||
+ long l; | |||
+ | |||
+ switch (xdrs->x_op) | |||
+ { | |||
+ case XDR_ENCODE: | |||
+ l = (long) *ip; | |||
+ return XDR_PUTLONG (xdrs, &l); | |||
+ | |||
+ case XDR_DECODE: | |||
+ if (!XDR_GETLONG (xdrs, &l)) | |||
+ { | |||
+ return FALSE; | |||
+ } | |||
+ *ip = (int) l; | |||
+ case XDR_FREE: | |||
+ return TRUE; | |||
+ } | |||
+ return FALSE; | |||
+#elif INT_MAX == LONG_MAX | |||
+ return xdr_long (xdrs, (long *) ip); | |||
+#elif INT_MAX == SHRT_MAX | |||
+ return xdr_short (xdrs, (short *) ip); | |||
+#else | |||
+#error unexpected integer sizes in xdr_int() | |||
+#endif | |||
+} | |||
+ | |||
+/* | |||
+ * XDR null terminated ASCII strings | |||
+ * xdr_string deals with "C strings" - arrays of bytes that are | |||
+ * terminated by a NULL character. The parameter cpp references a | |||
+ * pointer to storage; If the pointer is null, then the necessary | |||
+ * storage is allocated. The last parameter is the max allowed length | |||
+ * of the string as specified by a protocol. | |||
+ */ | |||
+bool_t | |||
+xdr_string (XDR *xdrs, char **cpp, u_int maxsize) | |||
+{ | |||
+ char *sp = *cpp; /* sp is the actual string pointer */ | |||
+ u_int size; | |||
+ u_int nodesize; | |||
+ | |||
+ /* | |||
+ * first deal with the length since xdr strings are counted-strings | |||
+ */ | |||
+ switch (xdrs->x_op) | |||
+ { | |||
+ case XDR_FREE: | |||
+ if (sp == NULL) | |||
+ { | |||
+ return TRUE; /* already free */ | |||
+ } | |||
+ /* fall through... */ | |||
+ case XDR_ENCODE: | |||
+ if (sp == NULL) | |||
+ return FALSE; | |||
+ size = strlen (sp); | |||
+ break; | |||
+ case XDR_DECODE: | |||
+ break; | |||
+ } | |||
+ if (!xdr_u_int (xdrs, &size)) | |||
+ { | |||
+ return FALSE; | |||
+ } | |||
+ if (size > maxsize) | |||
+ { | |||
+ return FALSE; | |||
+ } | |||
+ nodesize = size + 1; | |||
+ | |||
+ /* | |||
+ * now deal with the actual bytes | |||
+ */ | |||
+ switch (xdrs->x_op) | |||
+ { | |||
+ case XDR_DECODE: | |||
+ if (nodesize == 0) | |||
+ { | |||
+ return TRUE; | |||
+ } | |||
+ if (sp == NULL) | |||
+ *cpp = sp = (char *) mem_alloc (nodesize); | |||
+ if (sp == NULL) | |||
+ { | |||
+#ifdef USE_IN_LIBIO | |||
+ if (_IO_fwide (stderr, 0) > 0) | |||
+ (void) fwprintf (stderr, L"%s", | |||
+ _("xdr_string: out of memory\n")); | |||
+ else | |||
+#endif | |||
+ (void) fputs (_("xdr_string: out of memory\n"), stderr); | |||
+ return FALSE; | |||
+ } | |||
+ sp[size] = 0; | |||
+ /* fall into ... */ | |||
+ | |||
+ case XDR_ENCODE: | |||
+ return xdr_opaque (xdrs, sp, size); | |||
+ | |||
+ case XDR_FREE: | |||
+ mem_free (sp, nodesize); | |||
+ *cpp = NULL; | |||
+ return TRUE; | |||
+ } | |||
+ return FALSE; | |||
+} | |||
+ | |||
+/* | |||
+ * XDR long integers | |||
+ * The definition of xdr_long() is kept for backward | |||
+ * compatibility. Instead xdr_int() should be used. | |||
+ */ | |||
+bool_t | |||
+xdr_long (XDR *xdrs, long *lp) | |||
+{ | |||
+ if (xdrs->x_op == XDR_ENCODE | |||
+ && (sizeof (int32_t) == sizeof (long) | |||
+ || (int32_t) *lp == *lp)) | |||
+ return XDR_PUTLONG (xdrs, lp); | |||
+ | |||
+ if (xdrs->x_op == XDR_DECODE) | |||
+ return XDR_GETLONG (xdrs, lp); | |||
+ | |||
+ if (xdrs->x_op == XDR_FREE) | |||
+ return TRUE; | |||
+ | |||
+ return FALSE; | |||
+} | |||
+ | |||
+/* | |||
+ * XDR unsigned integers | |||
+ */ | |||
+bool_t | |||
+xdr_u_int (XDR *xdrs, u_int *up) | |||
+{ | |||
+#if UINT_MAX < ULONG_MAX | |||
+ u_long l; | |||
+ | |||
+ switch (xdrs->x_op) | |||
+ { | |||
+ case XDR_ENCODE: | |||
+ l = (u_long) * up; | |||
+ return XDR_PUTLONG (xdrs, (long *) &l); | |||
+ | |||
+ case XDR_DECODE: | |||
+ if (!XDR_GETLONG (xdrs, (long *) &l)) | |||
+ { | |||
+ return FALSE; | |||
+ } | |||
+ *up = (u_int) l; | |||
+ case XDR_FREE: | |||
+ return TRUE; | |||
+ } | |||
+ return FALSE; | |||
+#elif UINT_MAX == ULONG_MAX | |||
+ return xdr_u_long (xdrs, (u_long *) up); | |||
+#elif UINT_MAX == USHRT_MAX | |||
+ return xdr_short (xdrs, (short *) up); | |||
+#else | |||
+#error unexpected integer sizes in xdr_u_int() | |||
+#endif | |||
+} | |||
+ | |||
+/* | |||
+ * XDR opaque data | |||
+ * Allows the specification of a fixed size sequence of opaque bytes. | |||
+ * cp points to the opaque object and cnt gives the byte length. | |||
+ */ | |||
+bool_t | |||
+xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt) | |||
+{ | |||
+ u_int rndup; | |||
+ static char crud[BYTES_PER_XDR_UNIT]; | |||
+ | |||
+ /* | |||
+ * if no data we are done | |||
+ */ | |||
+ if (cnt == 0) | |||
+ return TRUE; | |||
+ | |||
+ /* | |||
+ * round byte count to full xdr units | |||
+ */ | |||
+ rndup = cnt % BYTES_PER_XDR_UNIT; | |||
+ if (rndup > 0) | |||
+ rndup = BYTES_PER_XDR_UNIT - rndup; | |||
+ | |||
+ switch (xdrs->x_op) | |||
+ { | |||
+ case XDR_DECODE: | |||
+ if (!XDR_GETBYTES (xdrs, cp, cnt)) | |||
+ { | |||
+ return FALSE; | |||
+ } | |||
+ if (rndup == 0) | |||
+ return TRUE; | |||
+ return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup); | |||
+ | |||
+ case XDR_ENCODE: | |||
+ if (!XDR_PUTBYTES (xdrs, cp, cnt)) | |||
+ { | |||
+ return FALSE; | |||
+ } | |||
+ if (rndup == 0) | |||
+ return TRUE; | |||
+ return XDR_PUTBYTES (xdrs, xdr_zero, rndup); | |||
+ | |||
+ case XDR_FREE: | |||
+ return TRUE; | |||
+ } | |||
+ return FALSE; | |||
+} | |||
+ | |||
+/* | |||
+ * XDR unsigned long integers | |||
+ * The definition of xdr_u_long() is kept for backward | |||
+ * compatibility. Instead xdr_u_int() should be used. | |||
+ */ | |||
+bool_t | |||
+xdr_u_long (XDR *xdrs, u_long *ulp) | |||
+{ | |||
+ switch (xdrs->x_op) | |||
+ { | |||
+ case XDR_DECODE: | |||
+ { | |||
+ long int tmp; | |||
+ | |||
+ if (XDR_GETLONG (xdrs, &tmp) == FALSE) | |||
+ return FALSE; | |||
+ | |||
+ *ulp = (uint32_t) tmp; | |||
+ return TRUE; | |||
+ } | |||
+ | |||
+ case XDR_ENCODE: | |||
+ if (sizeof (uint32_t) != sizeof (u_long) | |||
+ && (uint32_t) *ulp != *ulp) | |||
+ return FALSE; | |||
+ | |||
+ return XDR_PUTLONG (xdrs, (long *) ulp); | |||
+ | |||
+ case XDR_FREE: | |||
+ return TRUE; | |||
+ } | |||
+ return FALSE; | |||
+} | |||
+ | |||
+#endif /* UCLIBC */ | |||
+ | |||
bool_t | |||
xdr_xpasswd(XDR * xdrs, xpasswd * objp) | |||
{ |