aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac43
m---------grecs0
-rw-r--r--ident/Makefile.am35
-rw-r--r--ident/ident.c74
-rw-r--r--ident/ident.h51
-rw-r--r--ident/identity.h39
-rw-r--r--ident/pam.c230
-rw-r--r--ident/provider.c161
-rw-r--r--ident/system.c137
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/arraymember.c33
-rw-r--r--lib/libpies.h2
-rw-r--r--src/Makefile.am5
-rw-r--r--src/acl.c164
-rw-r--r--src/acl.h4
-rw-r--r--src/ctl.c68
-rw-r--r--src/inetd-bi.c2
-rw-r--r--src/pies.c63
-rw-r--r--src/pies.h7
-rw-r--r--src/progman.c10
21 files changed, 1053 insertions, 78 deletions
diff --git a/Makefile.am b/Makefile.am
index 63fdb48..0358e8c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,7 +16,7 @@
ACLOCAL_AMFLAGS = -I m4 -I am -I grecs/am -I imprimatur
-SUBDIRS=gnu grecs lib src imprimatur doc po
+SUBDIRS=gnu grecs lib ident src imprimatur doc po
dist-hook:
@PATCHLEV=`echo "$(PACKAGE_VERSION)" | \
diff --git a/configure.ac b/configure.ac
index 92ffbbd..8fb1eac 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
# This file is part of GNU Pies. -*- autoconf -*-
-# Copyright (C) 2009-2014 Sergey Poznyakoff
+# Copyright (C) 2009-2015 Sergey Poznyakoff
#
# GNU Pies is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -33,9 +33,12 @@ AC_PROG_YACC
AC_PROG_LEX
# Checks for libraries.
+AC_CHECK_LIB(crypt, crypt)
# Checks for header files.
-AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h string.h sys/socket.h sys/time.h syslog.h unistd.h utmp.h utmpx.h])
+AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h\
+ string.h sys/socket.h sys/time.h syslog.h unistd.h utmp.h utmpx.h\
+ crypt.h shadow.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@@ -80,6 +83,41 @@ AM_ICONV
AM_GNU_GETTEXT([external], [need-formatstring-macros])
AM_GNU_GETTEXT_VERSION([0.18])
+# PAM
+status_pam=maybe
+AC_ARG_ENABLE([pam],
+ AC_HELP_STRING([--enable-pam],
+ [enable PAM]),
+ [
+case "${enableval}" in
+ yes) status_pam=yes ;;
+ no) status_pam=no ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-pam]) ;;
+esac],[status_pam=maybe])
+
+AC_SUBST(PAM_LIBS,-lpam)
+if test "$status_pam" != "no"; then
+ pam=$status_pam
+ AC_CHECK_HEADERS(security/pam_appl.h)
+ if test "$ac_cv_header_security_pam_appl_h" = "yes"; then
+ AC_CHECK_LIB(dl, dlopen, [PAM_LIBS="$PAM_LIBS -ldl"])
+ AC_CHECK_LIB(pam, pam_start,
+ [status_pam=yes],
+ [status_pam=no], $PAM_LIBS)
+ else
+ status_pam=no
+ fi
+ if test $pam = yes && test $pam != $status_pam; then
+ AC_MSG_ERROR([required module PAM cannot be built because of missing prerequisites])
+ fi
+fi
+
+AM_CONDITIONAL([PAM_COND], [test $status_pam = yes])
+if test $status_pam = yes; then
+ AC_DEFINE_UNQUOTED(WITH_PAM, 1, [PAM support enabled])
+fi
+
+# Build inetd
AC_ARG_ENABLE([inetd],
AC_HELP_STRING([--enable-inetd],
[build and install a replacement for SBINDIR/inetd]),
@@ -100,6 +138,7 @@ AC_CONFIG_FILES([Makefile
gnu/Makefile
lib/Makefile
src/Makefile
+ ident/Makefile
doc/Makefile
po/Makefile.in])
AC_OUTPUT
diff --git a/grecs b/grecs
-Subproject e71c1a855797de245105494a05623753e32844a
+Subproject 9e978b089268e6bfc4b8fcdf9ef721f6fa92c11
diff --git a/ident/Makefile.am b/ident/Makefile.am
new file mode 100644
index 0000000..65ac145
--- /dev/null
+++ b/ident/Makefile.am
@@ -0,0 +1,35 @@
+# This file is part of GNU Pies.
+# Copyright (C) 2015 Sergey Poznyakoff
+#
+# GNU Pies 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.
+#
+# GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+noinst_LIBRARIES = libident.a
+noinst_HEADERS = ident.h identity.h
+
+libident_a_SOURCES = \
+ provider.c\
+ ident.c\
+ system.c
+
+if PAM_COND
+ libident_a_SOURCES += pam.c
+endif
+
+AM_CPPFLAGS=\
+ -I$(top_srcdir)/lib\
+ -I.\
+ -I$(top_srcdir)/gnu\
+ -I$(top_builddir)/gnu\
+ @GRECS_INCLUDES@
+
diff --git a/ident/ident.c b/ident/ident.c
new file mode 100644
index 0000000..38ae1a8
--- /dev/null
+++ b/ident/ident.c
@@ -0,0 +1,74 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2015 Sergey Poznyakoff
+
+ GNU Pies 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.
+
+ GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "ident.h"
+
+pies_identity_t
+pies_identity_create (char const *user)
+{
+ pies_identity_t id = xmalloc (sizeof (*id));
+ id->provider = NULL;
+ id->username = xstrdup (user);
+ id->data = NULL;
+ return id;
+}
+
+int
+pies_authenticate (pies_identity_provider_t pr, pies_identity_t id,
+ char const *passwd)
+{
+ if (!pr || !id)
+ return -1;
+
+ if (pr->mech->authenticate (pr, id, passwd) == 0)
+ {
+ id->provider = pr;
+ return 0;
+ }
+ return 1;
+}
+
+int
+pies_identity_is_user (pies_identity_t id, char * const * users)
+{
+ if (!id)
+ return 0;
+ return is_array_member (users, id->username);
+}
+
+int
+pies_identity_is_group_member (pies_identity_t id, char * const * groups)
+{
+ pies_identity_provider_t provider;
+ if (!id)
+ return 0;
+ provider = id->provider;
+ if (!provider)
+ return 0;
+ return provider->mech->is_group_member (provider, id, groups);
+}
+
+void
+pies_identity_destroy (pies_identity_t id)
+{
+ pies_identity_provider_t provider = id->provider;
+ if (provider && provider->mech->destroy_identity)
+ provider->mech->destroy_identity (provider, id);
+ free (id);
+}
+
+
+
diff --git a/ident/ident.h b/ident/ident.h
new file mode 100644
index 0000000..313926c
--- /dev/null
+++ b/ident/ident.h
@@ -0,0 +1,51 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2015 Sergey Poznyakoff
+
+ GNU Pies 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.
+
+ GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+#include "xalloc.h"
+#include "libpies.h"
+#include "grecs.h"
+#include "identity.h"
+
+struct pies_identity
+{
+ pies_identity_provider_t provider;
+ char *username;
+ void *data;
+};
+
+struct pies_identity_mechanism
+{
+ char const *name;
+ int (*authenticate) (pies_identity_provider_t p,
+ pies_identity_t id, char const *passwd);
+ int (*is_group_member) (pies_identity_provider_t p,
+ pies_identity_t id, char * const * groups);
+ void (*destroy_identity) (pies_identity_provider_t p,
+ pies_identity_t id);
+ int (*configure)(struct grecs_node *, pies_identity_provider_t);
+ void (*confhelp) (void);
+};
+
+struct pies_identity_provider
+{
+ char *name;
+ pies_identity_mechanism_t mech;
+ struct grecs_locus locus;
+ void *data;
+};
+
+
diff --git a/ident/identity.h b/ident/identity.h
new file mode 100644
index 0000000..0ee129d
--- /dev/null
+++ b/ident/identity.h
@@ -0,0 +1,39 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2015 Sergey Poznyakoff
+
+ GNU Pies 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.
+
+ GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+typedef struct pies_identity *pies_identity_t;
+typedef struct pies_identity_provider *pies_identity_provider_t;
+typedef struct pies_identity_mechanism *pies_identity_mechanism_t;
+
+pies_identity_t pies_identity_create (char const *user);
+void pies_identity_destroy (pies_identity_t id);
+
+int pies_authenticate (pies_identity_provider_t pr, pies_identity_t id,
+ char const *passwd);
+int pies_identity_is_user (pies_identity_t id, char * const * users);
+int pies_identity_is_group_member (pies_identity_t id, char * const * groups);
+
+char const *pies_identity_provider_name (pies_identity_provider_t p);
+
+int pies_identity_mechanism_register (pies_identity_mechanism_t mech);
+void pies_config_identity_mechanisms_help (void);
+int pies_config_provider (struct grecs_node *node);
+
+extern struct pies_identity_mechanism system_identity_mechanism;
+#ifdef WITH_PAM
+extern struct pies_identity_mechanism pam_identity_mechanism;
+#endif
+extern struct grecs_list *identity_provider_list;
diff --git a/ident/pam.c b/ident/pam.c
new file mode 100644
index 0000000..ef32c4d
--- /dev/null
+++ b/ident/pam.c
@@ -0,0 +1,230 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2015 Sergey Poznyakoff
+
+ GNU Pies 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.
+
+ GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "ident.h"
+#include <grp.h>
+#include <security/pam_appl.h>
+
+struct pam_identity_provider_data
+{
+ char *service;
+};
+
+struct pam_cred
+{
+ const char *user;
+ const char *pass;
+};
+
+#define COPY_STRING(s) (s) ? strdup(s) : NULL
+
+#define overwrite_and_free(ptr) \
+ do { \
+ char *s = ptr; \
+ while (*s) \
+ *s++ = 0; \
+ } while (0)
+
+#ifndef PAM_AUTHTOK_RECOVER_ERR
+# define PAM_AUTHTOK_RECOVER_ERR PAM_CONV_ERR
+#endif
+
+static int
+pies_conv (int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ int status = PAM_SUCCESS;
+ int i;
+ struct pam_response *reply = NULL;
+ struct pam_cred *cred = appdata_ptr;
+
+ reply = calloc (num_msg, sizeof (*reply));
+ if (!reply)
+ return PAM_CONV_ERR;
+
+ for (i = 0; i < num_msg && status == PAM_SUCCESS; i++)
+ {
+ switch (msg[i]->msg_style)
+ {
+ case PAM_PROMPT_ECHO_ON:
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = COPY_STRING (cred->user);
+ /* PAM frees resp */
+ break;
+
+ case PAM_PROMPT_ECHO_OFF:
+ if (cred->pass)
+ {
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = COPY_STRING (cred->pass);
+ /* PAM frees resp */
+ } else
+ status = PAM_AUTHTOK_RECOVER_ERR;
+ break;
+
+ case PAM_TEXT_INFO:
+ case PAM_ERROR_MSG:
+ reply[i].resp_retcode = PAM_SUCCESS;
+ reply[i].resp = NULL;
+ break;
+
+ default:
+ status = PAM_CONV_ERR;
+ }
+ }
+
+ if (status != PAM_SUCCESS)
+ {
+ for (i = 0; i < num_msg; i++)
+ if (reply[i].resp)
+ {
+ switch (msg[i]->msg_style)
+ {
+ case PAM_PROMPT_ECHO_ON:
+ case PAM_PROMPT_ECHO_OFF:
+ overwrite_and_free (reply[i].resp);
+ break;
+
+ case PAM_ERROR_MSG:
+ case PAM_TEXT_INFO:
+ free (reply[i].resp);
+ }
+ }
+ free (reply);
+ } else
+ *resp = reply;
+ return status;
+}
+
+static int
+authenticate (pies_identity_provider_t provider,
+ pies_identity_t id, char const *passwd)
+{
+ struct pam_identity_provider_data *pamdata = provider->data;
+ pam_handle_t *pamh;
+ int pamerror;
+ struct pam_cred cred = { id->username, passwd };
+ struct pam_conv pam_conv = { &pies_conv, &cred };
+ char const *service = pamdata->service ? pamdata->service : "pies";
+
+ do
+ {
+ pamerror = pam_start (service, id->username, &pam_conv, &pamh);
+ if (pamerror != PAM_SUCCESS)
+ break;
+
+ pamerror = pam_authenticate (pamh, 0);
+ if (pamerror != PAM_SUCCESS)
+ break;
+
+ pamerror = pam_acct_mgmt (pamh, 0);
+ if (pamerror != PAM_SUCCESS)
+ break;
+
+ pamerror = pam_setcred (pamh, PAM_ESTABLISH_CRED);
+ }
+ while (0);
+
+ pam_end (pamh, PAM_SUCCESS);
+
+ switch (pamerror)
+ {
+ case PAM_SUCCESS:
+ return 0;
+
+ case PAM_AUTH_ERR:
+ return -1;
+ }
+
+ //FIXME _log(L_ERR, 0, "PAM authentication error");
+ return -1;
+}
+
+static int
+is_group_member (pies_identity_provider_t p,
+ pies_identity_t id, char * const * groups)
+{
+ struct group *gr;
+ int result = 0;
+
+ setgrent ();
+ while ((gr = getgrent ()))
+ {
+ char **p;
+
+ if (!is_array_member (groups, gr->gr_name))
+ continue;
+
+ for (p = gr->gr_mem; *p; p++)
+ if (strcmp (*p, id->username) == 0)
+ {
+ result = 1;
+ break;
+ }
+ }
+ endgrent ();
+ return result;
+}
+
+static struct grecs_keyword pam_kw[] = {
+ { "type", "'pam", "Set mechanism type", grecs_type_null },
+ { "service", NULL, "Service name",
+ grecs_type_string, GRECS_DFLT, NULL,
+ offsetof(struct pam_identity_provider_data, service) },
+ { NULL }
+};
+
+static int
+configure (struct grecs_node *node, pies_identity_provider_t provider)
+{
+ int i;
+ struct pam_identity_provider_data *data = xcalloc (1, sizeof (*data));
+ provider->data = data;
+ for (i = 0; pam_kw[i].ident; i++)
+ pam_kw[i].varptr = data;
+ if (grecs_tree_process (node->down, pam_kw))
+ {
+ //FIXME: memory leak
+ return -1;
+ }
+ provider->locus = node->locus;
+ return 0;
+}
+
+static void
+confhelp (void)
+{
+ static struct grecs_keyword top[] = {
+ { "identity-provider", "name: string",
+ "Configuration for system identity provider",
+ grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL,
+ pam_kw },
+ { NULL }
+ };
+ grecs_print_statement_array (top, 1, 0, stdout);
+}
+
+struct pies_identity_mechanism pam_identity_mechanism = {
+ "pam",
+ authenticate,
+ is_group_member,
+ NULL,
+ configure,
+ confhelp
+};
+
+
+
diff --git a/ident/provider.c b/ident/provider.c
new file mode 100644
index 0000000..dd7fc3d
--- /dev/null
+++ b/ident/provider.c
@@ -0,0 +1,161 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2015 Sergey Poznyakoff
+
+ GNU Pies 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.
+
+ GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "ident.h"
+
+struct grecs_list *identity_provider_list;
+
+static struct grecs_symtab *idmech_symtab;
+
+static int
+idmech_copy (void *a, void *b)
+{
+ pies_identity_mechanism_t ma = a;
+ pies_identity_mechanism_t mb = b;
+
+ *ma = *mb;
+ ma->name = xstrdup (mb->name);
+ return 0;
+}
+
+int
+pies_identity_mechanism_register (pies_identity_mechanism_t mech)
+{
+ int install;
+
+ if (!idmech_symtab)
+ {
+ idmech_symtab = grecs_symtab_create (sizeof(*mech),
+ NULL,
+ NULL,
+ idmech_copy,
+ NULL,
+ NULL);
+ if (!idmech_symtab)
+ grecs_alloc_die();
+ }
+
+ install = 1;
+ if (!grecs_symtab_lookup_or_install (idmech_symtab, mech, &install))
+ abort ();
+ return !install;
+}
+
+pies_identity_mechanism_t
+pies_identity_mechanism_lookup (char const *name)
+{
+ struct pies_identity_mechanism key;
+ if (!idmech_symtab)
+ return NULL;
+ key.name = name;
+ return grecs_symtab_lookup_or_install (idmech_symtab, &key, NULL);
+}
+
+static int
+idmech_help (void *data, void *unused)
+{
+ pies_identity_mechanism_t p = data;
+
+ if (p->confhelp)
+ p->confhelp ();
+ return 0;
+}
+
+void
+pies_config_identity_mechanisms_help ()
+{
+ grecs_symtab_enumerate (idmech_symtab, idmech_help, NULL);
+}
+
+static int
+get_string_node (struct grecs_node *node, const char *name,
+ struct grecs_node **pret)
+{
+ struct grecs_node *p = grecs_find_node (node->down, name);
+
+ if (!p)
+ {
+ grecs_error (&node->locus, 0,
+ "no \"%s\" statement found", name);
+ return 1;
+ }
+
+ if (p->type != grecs_node_stmt)
+ {
+ grecs_error (&p->locus, 0, "must be simple statement");
+ return 1;
+ }
+
+ if (p->v.value->type != GRECS_TYPE_STRING)
+ {
+ grecs_error (&p->locus, 0, "must be scalar");
+ return 1;
+ }
+
+ *pret = p;
+ return 0;
+}
+
+int
+pies_config_provider (struct grecs_node *node)
+{
+ char const *name;
+ pies_identity_mechanism_t mp;
+ struct pies_identity_provider *prov;
+ struct grecs_node *p;
+
+ if (node->v.value->type != GRECS_TYPE_STRING)
+ {
+ grecs_error (&node->locus, 0, "value must be scalar");
+ return 1;
+ }
+
+ name = node->v.value->v.string;
+
+ if (get_string_node (node, "type", &p))
+ return 1;
+
+ mp = pies_identity_mechanism_lookup (p->v.value->v.string);
+ if (!mp)
+ {
+ grecs_error (&p->locus, 0, "no such mechanism");
+ return 1;
+ }
+
+ prov = xcalloc (1, sizeof (*prov));
+ prov->name = xstrdup (name);
+ prov->mech = mp;
+ prov->locus = node->locus;
+
+ if (mp->configure && mp->configure (node, prov))
+ {
+ grecs_error (&node->locus, 0, "provider configration failed");
+ //FIXME: memory leak
+ return 1;
+ }
+
+ if (!identity_provider_list)
+ identity_provider_list = grecs_list_create ();
+ grecs_list_append (identity_provider_list, prov);
+
+ return 0;
+}
+
+char const *
+pies_identity_provider_name (pies_identity_provider_t p)
+{
+ return p->name;
+}
diff --git a/ident/system.c b/ident/system.c
new file mode 100644
index 0000000..bde667c
--- /dev/null
+++ b/ident/system.c
@@ -0,0 +1,137 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2015 Sergey Poznyakoff
+
+ GNU Pies 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.
+
+ GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "ident.h"
+#include <sys/types.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#if defined(HAVE_CRYPT_H)
+# include <crypt.h>
+#endif
+#if defined(HAVE_SHADOW_H)
+# include <shadow.h>
+#endif
+
+struct system_identity_data
+{
+ gid_t gid;
+};
+
+static int
+system_authenticate (pies_identity_provider_t pr, pies_identity_t id,
+ char const *passwd)
+{
+ struct passwd *pwd;
+ char *encrypted_pass = NULL;
+
+ pwd = getpwnam (id->username);
+ if (!pwd)
+ return -1;
+
+ encrypted_pass = pwd->pw_passwd;
+
+#if defined(HAVE_SHADOW_H)
+ {
+ struct spwd *sp;
+ if ((sp = getspnam (id->username)) != NULL)
+ {
+ if (sp->sp_expire > 0 && time (NULL) > sp->sp_expire * 86400)
+ return -1;
+ encrypted_pass = sp->sp_pwdp;
+ }
+ }
+#endif
+
+ if (strcmp (crypt (passwd, encrypted_pass), encrypted_pass) == 0)
+ {
+ struct system_identity_data *data = xmalloc (sizeof (*data));
+ data->gid = pwd->pw_gid;
+ id->data = data;
+ return 0;
+ }
+ return -1;
+}
+
+static int
+system_is_group_member (pies_identity_provider_t provider,
+ pies_identity_t id, char * const * groups)
+{
+ struct system_identity_data *data = id->data;
+ struct group *gr;
+ int result = 0;
+
+ setgrent ();
+ while ((gr = getgrent ()))
+ {
+ char **p;
+
+ if (!is_array_member (groups, gr->gr_name))
+ continue;
+
+ if (gr->gr_gid == data->gid)
+ {
+ result = 1;
+ break;
+ }
+
+ for (p = gr->gr_mem; *p; p++)
+ if (strcmp (*p, id->username) == 0)
+ {
+ result = 1;
+ break;
+ }
+ }
+ endgrent ();
+ return result;
+}
+
+static void
+system_destroy_identity (pies_identity_provider_t p, pies_identity_t id)
+{
+ if (id->data)
+ free (id->data);
+}
+
+static void
+confhelp (void)
+{
+ static struct grecs_keyword kw[] = {
+ { "type", "'system", "Set mechanism type", grecs_type_null },
+ { NULL }
+ };
+
+ static struct grecs_keyword top[] = {
+ { "identity-provider", "name: string",
+ "Configuration for system identity provider",
+ grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL,
+ kw },
+ { NULL }
+ };
+ grecs_print_statement_array (top, 1, 0, stdout);
+}
+
+struct pies_identity_mechanism system_identity_mechanism = {
+ "system",
+ system_authenticate,
+ system_is_group_member,
+ system_destroy_identity,
+ NULL,
+ confhelp
+};
+
diff --git a/lib/Makefile.am b/lib/Makefile.am
index e389846..89812ca 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -19,6 +19,7 @@ noinst_LIBRARIES=libpies.a
noinst_HEADERS = libpies.h
libpies_a_SOURCES=\
+ arraymember.c\
parsetime.c\
proctitle.c\
strtotok.c
diff --git a/lib/arraymember.c b/lib/arraymember.c
new file mode 100644
index 0000000..14ace99
--- /dev/null
+++ b/lib/arraymember.c
@@ -0,0 +1,33 @@
+/* This file is part of GNU Pies.
+ Copyright (C) 2007, 2008, 2009, 2010, 2013 Sergey Poznyakoff
+
+ GNU Pies 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.
+
+ GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <string.h>
+#include "libpies.h"
+
+int
+is_array_member (char * const * ar, char const *str)
+{
+ for (; *ar; ++ar)
+ {
+ if (strcmp (*ar, str) == 0)
+ return 1;
+ }
+ return 0;
+}
+
diff --git a/lib/libpies.h b/lib/libpies.h
index 97188b6..b9c8af7 100644
--- a/lib/libpies.h
+++ b/lib/libpies.h
@@ -56,4 +56,6 @@ int strtotok_len_ci (struct tokendef *tab, const char *str, size_t len,
int strtotok (struct tokendef *tab, const char *str, int *pres);
int strtotok_ci (struct tokendef *tab, const char *str, int *pres);
int toktostr (struct tokendef *tab, int tok, const char **pres);
+
+int is_array_member (char * const * ar, char const *str);
diff --git a/src/Makefile.am b/src/Makefile.am
index 04634c7..ab4546f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -60,15 +60,18 @@ SUFFIXES=.opt .c .h
cmdline.h: cmdline.opt
LDADD = \
+ ../ident/libident.a\
../lib/libpies.a\
@GRECS_LDADD@\
../gnu/libgnu.a\
- $(MF_PROCTITLE_LIBS)
+ $(MF_PROCTITLE_LIBS)\
+ @PAM_LIBS@
pkgstatedir=$(localstatedir)/pies
AM_CPPFLAGS=\
-I$(top_srcdir)/lib\
+ -I$(top_srcdir)/ident\
-I$(top_srcdir)/gnu\
-I$(top_builddir)/gnu\
@GRECS_INCLUDES@\
diff --git a/src/acl.c b/src/acl.c
index 301f56f..fb6adfb 100644
--- a/src/acl.c
+++ b/src/acl.c
@@ -33,13 +33,21 @@ struct pies_sockaddr
struct sockaddr sa;
};
+enum name_match
+ {
+ match_none,
+ match_user_name,
+ match_group_name
+ };
+
struct acl_entry
{
grecs_locus_t locus;
int allow;
int authenticated;
pies_acl_t acl;
- struct grecs_list *groups;
+ enum name_match name_match;
+ char **names;
struct grecs_list *sockaddrs;
};
@@ -53,14 +61,61 @@ struct pies_acl
/* ACL creation */
+void
+grecs_locus_point_copy (struct grecs_locus_point *dst,
+ struct grecs_locus_point *src)
+{
+ dst->file = grecs_strdup (src->file);
+ dst->line = src->line;
+ dst->col = src->col;
+}
+
+void
+grecs_locus_copy (struct grecs_locus *dst, struct grecs_locus *src)
+{
+ grecs_locus_point_copy (&dst->beg, &src->beg);
+ grecs_locus_point_copy (&dst->end, &src->end);
+}
+
+void
+grecs_locus_point_free (struct grecs_locus_point *p)
+{
+ grecs_free (p->file);
+}
+
+void
+grecs_locus_free (struct grecs_locus *loc)
+{
+ grecs_locus_point_free (&loc->beg);
+ grecs_locus_point_free (&loc->end);
+}
+
+static void
+acl_free_entry (void *p)
+{
+ struct acl_entry *ent = p;
+ pies_acl_free (ent->acl);
+ grecs_locus_free (&ent->locus);
+ grecs_list_free (ent->sockaddrs);
+ if (ent->names)
+ {
+ size_t i;
+
+ for (i = 0; ent->names[i]; i++)
+ free (ent->names[i]);
+ free (ent->names);
+ }
+ free (ent);
+}
pies_acl_t
pies_acl_create (const char *name, grecs_locus_t *locus)
{
pies_acl_t acl = xmalloc (sizeof (acl[0]));
acl->name = name ? xstrdup (name) : NULL;
- acl->locus = *locus;
+ grecs_locus_copy (&acl->locus, locus);
acl->list = grecs_list_create ();
+ acl->list->free_entry = acl_free_entry;
return acl;
}
@@ -68,6 +123,7 @@ void
pies_acl_free (pies_acl_t acl)
{
free (acl->name);
+ grecs_locus_free (&acl->locus);
grecs_list_free (acl->list);
free (acl);
}
@@ -196,6 +252,12 @@ _parse_sockaddr (struct acl_entry *entry, const grecs_value_t *value)
return 0;
}
+static void
+sockaddr_free (void *p)
+{
+ free (p);
+}
+
static int
_parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
{
@@ -223,6 +285,7 @@ _parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
}
entry->sockaddrs = grecs_list_create ();
+ entry->sockaddrs->free_entry = sockaddr_free;
if (argv[0]->type == GRECS_TYPE_STRING)
{
if (_parse_sockaddr (entry, argv[0]))
@@ -288,22 +351,38 @@ static int
_parse_group (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
{
if (strcmp (argv[0]->v.string, "group") == 0)
+ entry->name_match = match_group_name;
+ else if (strcmp (argv[0]->v.string, "user") == 0)
+ entry->name_match = match_user_name;
+ else
+ entry->name_match = match_none;
+
+ if (entry->name_match != match_none)
{
argc--;
argv++;
if (argc == 0)
{
grecs_error (&entry->locus, 0,
- _("expected group list, but found end of statement"));