aboutsummaryrefslogtreecommitdiff
path: root/pam_innetgr
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-08-12 19:20:04 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-08-12 19:20:04 +0300
commit6bba235d667f25a9ae6bcd1c560b0ae28ea16505 (patch)
tree0d9e26952d7ae381f7dd78e6954fdda366a9eed7 /pam_innetgr
parent23b718d2a385bb07bcbd4584a694e9e75050098b (diff)
downloadpam-modules-6bba235d667f25a9ae6bcd1c560b0ae28ea16505.tar.gz
pam-modules-6bba235d667f25a9ae6bcd1c560b0ae28ea16505.tar.bz2
New module pam_innetgr.
* Makefile.am: Add new module. * NEWS: Upgrade * configure.ac: Add configuration for pam_innetgr * pam_innetgr/Makefile.am: New file. * pam_innetgr/pam_innetgr.c: New file. * doc/Makefile.am: Add pam_innetgr.8 * doc/pam-modules.texi: Document pam_innetgr. * doc/pam_innetgr.8: New file. * examples/ldappubkey: Bugfixes (publickeyattribute setting): Accept a list of attributes (publickeyfilter): New setting.
Diffstat (limited to 'pam_innetgr')
-rw-r--r--pam_innetgr/Makefile.am22
-rw-r--r--pam_innetgr/pam_innetgr.c319
2 files changed, 341 insertions, 0 deletions
diff --git a/pam_innetgr/Makefile.am b/pam_innetgr/Makefile.am
new file mode 100644
index 0000000..1e5c7f8
--- /dev/null
+++ b/pam_innetgr/Makefile.am
@@ -0,0 +1,22 @@
+# This file is part of pam-modules.
+# Copyright (C) 2018 Sergey Poznyakoff
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+
+include $(top_srcdir)/Make.rules
+
+pamdir=@PAMDIR@
+pam_LTLIBRARIES = pam_innetgr.la
+pam_innetgr_la_SOURCES = pam_innetgr.c
+AM_CPPFLAGS += -DMODULE_NAME=\"pam_innetgr\"
diff --git a/pam_innetgr/pam_innetgr.c b/pam_innetgr/pam_innetgr.c
new file mode 100644
index 0000000..f1f5e5d
--- /dev/null
+++ b/pam_innetgr/pam_innetgr.c
@@ -0,0 +1,319 @@
+/* This file is part of pam-modules.
+ Copyright (C) 2018 Sergey Poznyakoff
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE__PAM_ACONF_H
+#include <security/_pam_aconf.h>
+#endif
+#include <stdlib.h>
+#include <netdb.h>
+#include "graypam.h"
+
+#ifndef LINUX_PAM
+#include <security/pam_appl.h>
+#endif
+#include <security/pam_modules.h>
+
+static long debug_level;
+char const *host_name;
+char const *domain_name;
+char const *netgroup_name;
+int use_getdomainname;
+int use_resolve;
+enum {
+ SENSE_ALLOW,
+ SENSE_DENY
+};
+const char *sense_choice[] = { "allow", "deny", NULL };
+static int sense;
+
+struct pam_opt pam_opt[] = {
+ { PAM_OPTSTR(debug), pam_opt_long, &debug_level },
+ { PAM_OPTSTR(debug), pam_opt_const, &debug_level, { 1 } },
+ { PAM_OPTSTR(audit), pam_opt_const, &debug_level, { 100 } },
+ { PAM_OPTSTR(waitdebug), pam_opt_null, NULL, { 0 },
+ gray_wait_debug_fun },
+ { PAM_OPTSTR(netgroup), pam_opt_string, &netgroup_name },
+ { PAM_OPTSTR(hostname), pam_opt_string, &host_name },
+ { PAM_OPTSTR(domainname), pam_opt_string, &domain_name },
+ { PAM_OPTSTR(getdomainname), pam_opt_bool, &use_getdomainname },
+ { PAM_OPTSTR(resolve), pam_opt_bool, &use_resolve },
+ { PAM_OPTSTR(sense), pam_opt_enum, &sense, { enumstr: sense_choice } },
+ { NULL }
+};
+
+#ifndef MAXHOSTNAMELEN
+# define MAXHOSTNAMELEN 64
+#endif
+#ifndef SIZE_T_MAX
+# define SIZE_T_MAX ((size_t)-1)
+#endif
+
+int
+xgetname (int (*getfn)(char *, size_t), char **storage)
+{
+ char *buffer = NULL;
+ size_t size = 0;
+ char *p;
+
+ while (1) {
+ if (size == 0) {
+ size = MAXHOSTNAMELEN;
+ p = malloc(size);
+ } else if (SIZE_T_MAX / 3 * 2 <= size) {
+ p = NULL;
+ } else {
+ size += (size + 1) / 2;
+ p = realloc(buffer, size);
+ }
+ if (!p) {
+ free(buffer);
+ errno = ENOMEM;
+ return -1;
+ }
+ buffer = p;
+ buffer[size - 1] = 0;
+ if (getfn(buffer, size - 1) == 0) {
+ if (!buffer[size - 1])
+ break;
+ } else if (errno != 0
+ && errno != ENAMETOOLONG
+ && errno != EINVAL
+ && errno != ENOMEM) {
+ int rc = errno;
+ free(buffer);
+ errno = rc;
+ return -1;
+ }
+ }
+ *storage = buffer;
+
+ return 0;
+}
+
+int
+stripdomain(char *hostname, char const *domainname)
+{
+ size_t hlen, dlen;
+
+ if (!domainname)
+ return -1;
+ hlen = strlen(hostname);
+ dlen = strlen(domainname);
+ if (hlen > dlen + 1
+ && hostname[hlen - dlen - 1] == '.'
+ && strcasecmp(hostname + hlen - dlen, domainname) == 0) {
+ hostname[hlen - dlen - 1] = 0;
+ return 0;
+ }
+ return -1;
+}
+
+int
+get_host_domain_names(char **host_name_ptr, char **domain_name_ptr)
+{
+ char *hostname;
+ char *domainname = NULL;
+
+ if (xgetname(gethostname, &hostname))
+ return -1;
+#if HAVE_GETDOMAINNAME
+ if (use_getdomainname) {
+ if (xgetname(getdomainname, &domainname)) {
+ _pam_log(LOG_ERR, "getdomainname: %s", strerror(errno));
+ } else if (strcmp (domainname, "(none)") == 0) {
+ free(domainname);
+ domainname = NULL;
+ }
+ }
+#endif
+ if (domainname) {
+ stripdomain(hostname, domainname);
+ } else if (use_resolve) {
+ char *p = strchr(hostname, '.');
+ if (!p) {
+ struct hostent *hp = gethostbyname(hostname);
+ if (hp) {
+ size_t len = strlen(hp->h_name);
+ p = realloc(hostname, len + 1);
+ if (!p) {
+ free(hostname);
+ errno = ENOMEM;
+ return -1;
+ }
+ hostname = p;
+ strcpy(hostname, hp->h_name);
+ p = strchr(hostname, '.');
+ }
+ }
+ if (p) {
+ *p++ = 0;
+ domainname = strdup(p);
+ if (!domainname) {
+ int rc = errno;
+ _pam_log(LOG_ERR, "getdomainname: %s",
+ strerror(errno));
+ free(hostname);
+ errno = rc;
+ return -1;
+ }
+ }
+ }
+
+ *host_name_ptr = hostname;
+ *domain_name_ptr = domainname;
+
+ return 0;
+}
+
+static int
+check_netgroup0(pam_handle_t *pamh, int argc, const char **argv,
+ const char *func)
+{
+ int rc;
+ char *host_name_buf = NULL;
+ char *domain_name_buf = NULL;
+ char const *user_name;
+
+ debug_level = 0;
+ host_name = NULL;
+ domain_name = NULL;
+ netgroup_name = NULL;
+ use_getdomainname = 1;
+ use_resolve = 1;
+ sense = SENSE_ALLOW;
+
+ gray_pam_init(PAM_AUTHINFO_UNAVAIL);
+ gray_log_init(0, MODULE_NAME, LOG_AUTHPRIV);
+ gray_parseopt(pam_opt, argc, argv);
+ if (!netgroup_name) {
+ _pam_log(LOG_ERR, "no netgroup name given");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ /*
+ * get username
+ */
+ rc = pam_get_user(pamh, &user_name, "login: ");
+ if (rc == PAM_SUCCESS) {
+ DEBUG(10, ("username [%s] obtained", user_name));
+ } else {
+ _pam_log(LOG_NOTICE, "can't get username");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+
+ if (!host_name || !domain_name) {
+ if (get_host_domain_names (&host_name_buf, &domain_name_buf)) {
+ _pam_log(LOG_ERR, "%s", strerror(errno));
+ return PAM_SERVICE_ERR;
+ }
+ if (!host_name) {
+ if (!host_name_buf) {
+ _pam_log(LOG_NOTICE, "can't get hostname");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+ host_name = host_name_buf;
+ }
+ if (!domain_name) {
+ if (!domain_name_buf) {
+ _pam_log(LOG_NOTICE, "can't get domainname");
+ return PAM_AUTHINFO_UNAVAIL;
+ }
+ domain_name = domain_name_buf;
+ }
+ }
+
+ DEBUG(1,("checking (%s, %s, %s)",
+ host_name, user_name, domain_name));
+
+ rc = innetgr(netgroup_name, host_name, user_name, domain_name);
+
+ DEBUG(1,("netgroup %s, triple (%s, %s, %s): %d", netgroup_name,
+ host_name, user_name, domain_name, rc));
+
+ free(host_name_buf);
+ free(domain_name_buf);
+
+ if (sense == SENSE_DENY)
+ rc = !rc;
+ return rc ? PAM_SUCCESS : PAM_AUTH_ERR;
+}
+
+static int
+check_netgroup(pam_handle_t *pamh, int argc, const char **argv,
+ const char *func)
+{
+ int rc;
+
+ DEBUG(90,("enter %s", func));
+ rc = check_netgroup0(pamh, argc, argv, __FUNCTION__);
+ DEBUG(90,("leave %s=%d", func, rc));
+ return rc;
+}
+
+PAM_EXTERN int
+pam_sm_authenticate(pam_handle_t *pamh,
+ int flags,
+ int argc,
+ const char **argv)
+{
+ return check_netgroup(pamh, argc, argv, __FUNCTION__);
+}
+
+PAM_EXTERN int
+pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv)
+{
+ return check_netgroup(pamh, argc, argv, __FUNCTION__);
+}
+
+PAM_EXTERN int
+pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, int argc, const char **argv)
+{
+ return check_netgroup(pamh, argc, argv, __FUNCTION__);
+}
+
+PAM_EXTERN int
+pam_sm_open_session (pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ return check_netgroup(pamh, argc, argv, __FUNCTION__);
+}
+
+PAM_EXTERN int
+pam_sm_close_session (pam_handle_t *pamh, int flags, int argc,
+ const char **argv)
+{
+ return check_netgroup(pamh, argc, argv, __FUNCTION__);
+}
+
+#ifdef PAM_STATIC
+
+/* static module data */
+
+struct pam_module _pam_log_modstruct = {
+ MODULE_NAME,
+ pam_sm_authenticate,
+ pam_sm_setcred,
+ pam_sm_acct_mgmt,
+ pam_sm_open_session,
+ pam_sm_close_session,
+ pam_sm_chauthtok,
+};
+
+#endif
+
+/* end of module definition */
+
+

Return to:

Send suggestions and report system problems to the System administrator.