aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2015-12-16 14:58:07 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2015-12-16 14:58:07 +0200
commit6bb908898b833ec69c66e918de732af5bad68934 (patch)
treedd715a052f67849d38aedaa25eafa93241e938df
parent9cb7455b12462a3679ed5208540793d802570481 (diff)
downloadpies-6bb908898b833ec69c66e918de732af5bad68934.tar.gz
pies-6bb908898b833ec69c66e918de732af5bad68934.tar.bz2
Implement authentication on control socket.
* Makefile.am (SUBDIRS): Add src. * configure.ac: Check for crypt.h and PAM Build ident/Makefile * grecs: Update. * ident/Makefile.am: New file. * ident/ident.c: New file. * ident/ident.h: New file. * ident/identity.h: New file. * ident/pam.c: New file. * ident/provider.c: New file. * ident/system.c: New file. * lib/Makefile.am: Add arraymember.c * lib/arraymember.c: New file. * lib/libpies.h (is_array_member): New proto. * src/Makefile.am (LDADD): Add libident.a and @PAM_LIBS@ * src/acl.c (acl_entry): Remove groups. Add new members: names and name_match. (pies_acl_create): Deep copy the locus. Set free_entry function for the list. (pies_acl_free): Free locus. (_parse_from): Set free_entry function for the list. (_parse_group): Parse the "user" construct. (parse_acl_line): Deep copy the locus. Allow for null value. (acl_keywords): Update docstrings. (_acl_check): Rewrite identity checks. * src/acl.h (acl_input)<user,groups>: Remove. <identity>: New member. (pies_acl_free): New proto. * src/ctl.c (identity): New global. (cmdtab): New command: auth (ctlio) <addr,addrlen>: New members. (ctlio_create): Start from authenticated state only if no identity_providers are configured. (cmd_auth): New function. (cmd_help): Print only commands that are available in the current state. (ctl_accept): Initialize io->addr and io->addrlen. * src/inetd-bi.c: Change call to check_acl * src/pies.c: Include identity.h (control_keywords): New statement "identity-acl" (pies_keywords): New statement "identity-provider" (config_init): Register identity mechanisms. (config_parse): New function. (config_help): Print help on identity-provider statements. (main): Use config_parse to parse grecs-style configurations. * src/pies.h: Include identity.h (check_acl): Change argument list. All callers changed. (control): Remove acl. Add conn_acl and id_acl instead. * src/progman.c (check_acl): Change argument list. Take identity as the 3rd argument.
-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 @@
16 16
17ACLOCAL_AMFLAGS = -I m4 -I am -I grecs/am -I imprimatur 17ACLOCAL_AMFLAGS = -I m4 -I am -I grecs/am -I imprimatur
18 18
19SUBDIRS=gnu grecs lib src imprimatur doc po 19SUBDIRS=gnu grecs lib ident src imprimatur doc po
20 20
21dist-hook: 21dist-hook:
22 @PATCHLEV=`echo "$(PACKAGE_VERSION)" | \ 22 @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 @@
1# This file is part of GNU Pies. -*- autoconf -*- 1# This file is part of GNU Pies. -*- autoconf -*-
2# Copyright (C) 2009-2014 Sergey Poznyakoff 2# Copyright (C) 2009-2015 Sergey Poznyakoff
3# 3#
4# GNU Pies is free software; you can redistribute it and/or modify 4# GNU Pies is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by 5# it under the terms of the GNU General Public License as published by
@@ -33,9 +33,12 @@ AC_PROG_YACC
33AC_PROG_LEX 33AC_PROG_LEX
34 34
35# Checks for libraries. 35# Checks for libraries.
36AC_CHECK_LIB(crypt, crypt)
36 37
37# Checks for header files. 38# Checks for header files.
38AC_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]) 39AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdint.h stdlib.h\
40 string.h sys/socket.h sys/time.h syslog.h unistd.h utmp.h utmpx.h\
41 crypt.h shadow.h])
39 42
40# Checks for typedefs, structures, and compiler characteristics. 43# Checks for typedefs, structures, and compiler characteristics.
41AC_TYPE_UID_T 44AC_TYPE_UID_T
@@ -80,6 +83,41 @@ AM_ICONV
80AM_GNU_GETTEXT([external], [need-formatstring-macros]) 83AM_GNU_GETTEXT([external], [need-formatstring-macros])
81AM_GNU_GETTEXT_VERSION([0.18]) 84AM_GNU_GETTEXT_VERSION([0.18])
82 85
86# PAM
87status_pam=maybe
88AC_ARG_ENABLE([pam],
89 AC_HELP_STRING([--enable-pam],
90 [enable PAM]),
91 [
92case "${enableval}" in
93 yes) status_pam=yes ;;
94 no) status_pam=no ;;
95 *) AC_MSG_ERROR([bad value ${enableval} for --enable-pam]) ;;
96esac],[status_pam=maybe])
97
98AC_SUBST(PAM_LIBS,-lpam)
99if test "$status_pam" != "no"; then
100 pam=$status_pam
101 AC_CHECK_HEADERS(security/pam_appl.h)
102 if test "$ac_cv_header_security_pam_appl_h" = "yes"; then
103 AC_CHECK_LIB(dl, dlopen, [PAM_LIBS="$PAM_LIBS -ldl"])
104 AC_CHECK_LIB(pam, pam_start,
105 [status_pam=yes],
106 [status_pam=no], $PAM_LIBS)
107 else
108 status_pam=no
109 fi
110 if test $pam = yes && test $pam != $status_pam; then
111 AC_MSG_ERROR([required module PAM cannot be built because of missing prerequisites])
112 fi
113fi
114
115AM_CONDITIONAL([PAM_COND], [test $status_pam = yes])
116if test $status_pam = yes; then
117 AC_DEFINE_UNQUOTED(WITH_PAM, 1, [PAM support enabled])
118fi
119
120# Build inetd
83AC_ARG_ENABLE([inetd], 121AC_ARG_ENABLE([inetd],
84 AC_HELP_STRING([--enable-inetd], 122 AC_HELP_STRING([--enable-inetd],
85 [build and install a replacement for SBINDIR/inetd]), 123 [build and install a replacement for SBINDIR/inetd]),
@@ -100,6 +138,7 @@ AC_CONFIG_FILES([Makefile
100 gnu/Makefile 138 gnu/Makefile
101 lib/Makefile 139 lib/Makefile
102 src/Makefile 140 src/Makefile
141 ident/Makefile
103 doc/Makefile 142 doc/Makefile
104 po/Makefile.in]) 143 po/Makefile.in])
105AC_OUTPUT 144AC_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 @@
1# This file is part of GNU Pies.
2# Copyright (C) 2015 Sergey Poznyakoff
3#
4# GNU Pies is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 3, or (at your option)
7# any later version.
8#
9# GNU Pies is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17noinst_LIBRARIES = libident.a
18noinst_HEADERS = ident.h identity.h
19
20libident_a_SOURCES = \
21 provider.c\
22 ident.c\
23 system.c
24
25if PAM_COND
26 libident_a_SOURCES += pam.c
27endif
28
29AM_CPPFLAGS=\
30 -I$(top_srcdir)/lib\
31 -I.\
32 -I$(top_srcdir)/gnu\
33 -I$(top_builddir)/gnu\
34 @GRECS_INCLUDES@
35
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 @@
1/* This file is part of GNU Pies.
2 Copyright (C) 2015 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "ident.h"
18
19pies_identity_t
20pies_identity_create (char const *user)
21{
22 pies_identity_t id = xmalloc (sizeof (*id));
23 id->provider = NULL;
24 id->username = xstrdup (user);
25 id->data = NULL;
26 return id;
27}
28
29int
30pies_authenticate (pies_identity_provider_t pr, pies_identity_t id,
31 char const *passwd)
32{
33 if (!pr || !id)
34 return -1;
35
36 if (pr->mech->authenticate (pr, id, passwd) == 0)
37 {
38 id->provider = pr;
39 return 0;
40 }
41 return 1;
42}
43
44int
45pies_identity_is_user (pies_identity_t id, char * const * users)
46{
47 if (!id)
48 return 0;
49 return is_array_member (users, id->username);
50}
51
52int
53pies_identity_is_group_member (pies_identity_t id, char * const * groups)
54{
55 pies_identity_provider_t provider;
56 if (!id)
57 return 0;
58 provider = id->provider;
59 if (!provider)
60 return 0;
61 return provider->mech->is_group_member (provider, id, groups);
62}
63
64void
65pies_identity_destroy (pies_identity_t id)
66{
67 pies_identity_provider_t provider = id->provider;
68 if (provider && provider->mech->destroy_identity)
69 provider->mech->destroy_identity (provider, id);
70 free (id);
71}
72
73
74
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 @@
1/* This file is part of GNU Pies.
2 Copyright (C) 2015 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17#include <config.h>
18#include "xalloc.h"
19#include "libpies.h"
20#include "grecs.h"
21#include "identity.h"
22
23struct pies_identity
24{
25 pies_identity_provider_t provider;
26 char *username;
27 void *data;
28};
29
30struct pies_identity_mechanism
31{
32 char const *name;
33 int (*authenticate) (pies_identity_provider_t p,
34 pies_identity_t id, char const *passwd);
35 int (*is_group_member) (pies_identity_provider_t p,
36 pies_identity_t id, char * const * groups);
37 void (*destroy_identity) (pies_identity_provider_t p,
38 pies_identity_t id);
39 int (*configure)(struct grecs_node *, pies_identity_provider_t);
40 void (*confhelp) (void);
41};
42
43struct pies_identity_provider
44{
45 char *name;
46 pies_identity_mechanism_t mech;
47 struct grecs_locus locus;
48 void *data;
49};
50
51
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 @@
1/* This file is part of GNU Pies.
2 Copyright (C) 2015 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17typedef struct pies_identity *pies_identity_t;
18typedef struct pies_identity_provider *pies_identity_provider_t;
19typedef struct pies_identity_mechanism *pies_identity_mechanism_t;
20
21pies_identity_t pies_identity_create (char const *user);
22void pies_identity_destroy (pies_identity_t id);
23
24int pies_authenticate (pies_identity_provider_t pr, pies_identity_t id,
25 char const *passwd);
26int pies_identity_is_user (pies_identity_t id, char * const * users);
27int pies_identity_is_group_member (pies_identity_t id, char * const * groups);
28
29char const *pies_identity_provider_name (pies_identity_provider_t p);
30
31int pies_identity_mechanism_register (pies_identity_mechanism_t mech);
32void pies_config_identity_mechanisms_help (void);
33int pies_config_provider (struct grecs_node *node);
34
35extern struct pies_identity_mechanism system_identity_mechanism;
36#ifdef WITH_PAM
37extern struct pies_identity_mechanism pam_identity_mechanism;
38#endif
39extern 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 @@
1/* This file is part of GNU Pies.
2 Copyright (C) 2015 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "ident.h"
18#include <grp.h>
19#include <security/pam_appl.h>
20
21struct pam_identity_provider_data
22{
23 char *service;
24};
25
26struct pam_cred
27{
28 const char *user;
29 const char *pass;
30};
31
32#define COPY_STRING(s) (s) ? strdup(s) : NULL
33
34#define overwrite_and_free(ptr) \
35 do { \
36 char *s = ptr; \
37 while (*s) \
38 *s++ = 0; \
39 } while (0)
40
41#ifndef PAM_AUTHTOK_RECOVER_ERR
42# define PAM_AUTHTOK_RECOVER_ERR PAM_CONV_ERR
43#endif
44
45static int
46pies_conv (int num_msg, const struct pam_message **msg,
47 struct pam_response **resp, void *appdata_ptr)
48{
49 int status = PAM_SUCCESS;
50 int i;
51 struct pam_response *reply = NULL;
52 struct pam_cred *cred = appdata_ptr;
53
54 reply = calloc (num_msg, sizeof (*reply));
55 if (!reply)
56 return PAM_CONV_ERR;
57
58 for (i = 0; i < num_msg && status == PAM_SUCCESS; i++)
59 {
60 switch (msg[i]->msg_style)
61 {
62 case PAM_PROMPT_ECHO_ON:
63 reply[i].resp_retcode = PAM_SUCCESS;
64 reply[i].resp = COPY_STRING (cred->user);
65 /* PAM frees resp */
66 break;
67
68 case PAM_PROMPT_ECHO_OFF:
69 if (cred->pass)
70 {
71 reply[i].resp_retcode = PAM_SUCCESS;
72 reply[i].resp = COPY_STRING (cred->pass);
73 /* PAM frees resp */
74 } else
75 status = PAM_AUTHTOK_RECOVER_ERR;
76 break;
77
78 case PAM_TEXT_INFO:
79 case PAM_ERROR_MSG:
80 reply[i].resp_retcode = PAM_SUCCESS;
81 reply[i].resp = NULL;
82 break;
83
84 default:
85 status = PAM_CONV_ERR;
86 }
87 }
88
89 if (status != PAM_SUCCESS)
90 {
91 for (i = 0; i < num_msg; i++)
92 if (reply[i].resp)
93 {
94 switch (msg[i]->msg_style)
95 {
96 case PAM_PROMPT_ECHO_ON:
97 case PAM_PROMPT_ECHO_OFF:
98 overwrite_and_free (reply[i].resp);
99 break;
100
101 case PAM_ERROR_MSG:
102 case PAM_TEXT_INFO:
103 free (reply[i].resp);
104 }
105 }
106 free (reply);
107 } else
108 *resp = reply;
109 return status;
110}
111
112static int
113authenticate (pies_identity_provider_t provider,
114 pies_identity_t id, char const *passwd)
115{
116 struct pam_identity_provider_data *pamdata = provider->data;
117 pam_handle_t *pamh;
118 int pamerror;
119 struct pam_cred cred = { id->username, passwd };
120 struct pam_conv pam_conv = { &pies_conv, &cred };
121 char const *service = pamdata->service ? pamdata->service : "pies";
122
123 do
124 {
125 pamerror = pam_start (service, id->username, &pam_conv, &pamh);
126 if (pamerror != PAM_SUCCESS)
127 break;
128
129 pamerror = pam_authenticate (pamh, 0);
130 if (pamerror != PAM_SUCCESS)
131 break;
132
133 pamerror = pam_acct_mgmt (pamh, 0);
134 if (pamerror != PAM_SUCCESS)
135 break;
136
137 pamerror = pam_setcred (pamh, PAM_ESTABLISH_CRED);
138 }
139 while (0);
140
141 pam_end (pamh, PAM_SUCCESS);
142
143 switch (pamerror)
144 {
145 case PAM_SUCCESS:
146 return 0;
147
148 case PAM_AUTH_ERR:
149 return -1;
150 }
151
152 //FIXME _log(L_ERR, 0, "PAM authentication error");
153 return -1;
154}
155
156static int
157is_group_member (pies_identity_provider_t p,
158 pies_identity_t id, char * const * groups)
159{
160 struct group *gr;
161 int result = 0;
162
163 setgrent ();
164 while ((gr = getgrent ()))
165 {
166 char **p;
167
168 if (!is_array_member (groups, gr->gr_name))
169 continue;
170
171 for (p = gr->gr_mem; *p; p++)
172 if (strcmp (*p, id->username) == 0)
173 {
174 result = 1;
175 break;
176 }
177 }
178 endgrent ();
179 return result;
180}
181
182static struct grecs_keyword pam_kw[] = {
183 { "type", "'pam", "Set mechanism type", grecs_type_null },
184 { "service", NULL, "Service name",
185 grecs_type_string, GRECS_DFLT, NULL,
186 offsetof(struct pam_identity_provider_data, service) },
187 { NULL }
188};
189
190static int
191configure (struct grecs_node *node, pies_identity_provider_t provider)
192{
193 int i;
194 struct pam_identity_provider_data *data = xcalloc (1, sizeof (*data));
195 provider->data = data;
196 for (i = 0; pam_kw[i].ident; i++)
197 pam_kw[i].varptr = data;
198 if (grecs_tree_process (node->down, pam_kw))
199 {
200 //FIXME: memory leak
201 return -1;
202 }
203 provider->locus = node->locus;
204 return 0;
205}
206
207static void
208confhelp (void)
209{
210 static struct grecs_keyword top[] = {
211 { "identity-provider", "name: string",
212 "Configuration for system identity provider",
213 grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL,
214 pam_kw },
215 { NULL }
216 };
217 grecs_print_statement_array (top, 1, 0, stdout);
218}
219
220struct pies_identity_mechanism pam_identity_mechanism = {
221 "pam",
222 authenticate,
223 is_group_member,
224 NULL,
225 configure,
226 confhelp
227};
228
229
230
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 @@
1/* This file is part of GNU Pies.
2 Copyright (C) 2015 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "ident.h"
18
19struct grecs_list *identity_provider_list;
20
21static struct grecs_symtab *idmech_symtab;
22
23static int
24idmech_copy (void *a, void *b)
25{
26 pies_identity_mechanism_t ma = a;
27 pies_identity_mechanism_t mb = b;
28
29 *ma = *mb;
30 ma->name = xstrdup (mb->name);
31 return 0;
32}
33
34int
35pies_identity_mechanism_register (pies_identity_mechanism_t mech)
36{
37 int install;
38
39 if (!idmech_symtab)
40 {
41 idmech_symtab = grecs_symtab_create (sizeof(*mech),
42 NULL,
43 NULL,
44 idmech_copy,
45 NULL,
46 NULL);
47 if (!idmech_symtab)
48 grecs_alloc_die();
49 }
50
51 install = 1;
52 if (!grecs_symtab_lookup_or_install (idmech_symtab, mech, &install))
53 abort ();
54 return !install;
55}
56
57pies_identity_mechanism_t
58pies_identity_mechanism_lookup (char const *name)
59{
60 struct pies_identity_mechanism key;
61 if (!idmech_symtab)
62 return NULL;
63 key.name = name;
64 return grecs_symtab_lookup_or_install (idmech_symtab, &key, NULL);
65}
66
67static int
68idmech_help (void *data, void *unused)
69{
70 pies_identity_mechanism_t p = data;
71
72 if (p->confhelp)
73 p->confhelp ();
74 return 0;
75}
76
77void
78pies_config_identity_mechanisms_help ()
79{
80 grecs_symtab_enumerate (idmech_symtab, idmech_help, NULL);
81}
82
83static int
84get_string_node (struct grecs_node *node, const char *name,
85 struct grecs_node **pret)
86{
87 struct grecs_node *p = grecs_find_node (node->down, name);
88
89 if (!p)
90 {
91 grecs_error (&node->locus, 0,
92 "no \"%s\" statement found", name);
93 return 1;
94 }
95
96 if (p->type != grecs_node_stmt)
97 {
98 grecs_error (&p->locus, 0, "must be simple statement");
99 return 1;
100 }
101
102 if (p->v.value->type != GRECS_TYPE_STRING)
103 {
104 grecs_error (&p->locus, 0, "must be scalar");
105 return 1;
106 }
107
108 *pret = p;
109 return 0;
110}
111
112int
113pies_config_provider (struct grecs_node *node)
114{
115 char const *name;
116 pies_identity_mechanism_t mp;
117 struct pies_identity_provider *prov;
118 struct grecs_node *p;
119
120 if (node->v.value->type != GRECS_TYPE_STRING)
121 {
122 grecs_error (&node->locus, 0, "value must be scalar");
123 return 1;
124 }
125
126 name = node->v.value->v.string;
127
128 if (get_string_node (node, "type", &p))
129 return 1;
130
131 mp = pies_identity_mechanism_lookup (p->v.value->v.string);
132 if (!mp)
133 {
134 grecs_error (&p->locus, 0, "no such mechanism");
135 return 1;
136 }
137
138 prov = xcalloc (1, sizeof (*prov));
139 prov->name = xstrdup (name);
140 prov->mech = mp;
141 prov->locus = node->locus;
142
143 if (mp->configure && mp->configure (node, prov))
144 {
145 grecs_error (&node->locus, 0, "provider configration failed");
146 //FIXME: memory leak
147 return 1;
148 }
149
150 if (!identity_provider_list)
151 identity_provider_list = grecs_list_create ();
152 grecs_list_append (identity_provider_list, prov);
153
154 return 0;
155}
156
157char const *
158pies_identity_provider_name (pies_identity_provider_t p)
159{
160 return p->name;
161}
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 @@
1/* This file is part of GNU Pies.
2 Copyright (C) 2015 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "ident.h"
18#include <sys/types.h>
19#include <pwd.h>
20#include <grp.h>
21#include <unistd.h>
22#include <string.h>
23#include <time.h>
24#if defined(HAVE_CRYPT_H)
25# include <crypt.h>
26#endif
27#if defined(HAVE_SHADOW_H)
28# include <shadow.h>
29#endif
30
31struct system_identity_data
32{
33 gid_t gid;
34};
35
36static int
37system_authenticate (pies_identity_provider_t pr, pies_identity_t id,
38 char const *passwd)
39{
40 struct passwd *pwd;
41 char *encrypted_pass = NULL;
42
43 pwd = getpwnam (id->username);
44 if (!pwd)
45 return -1;
46
47 encrypted_pass = pwd->pw_passwd;
48
49#if defined(HAVE_SHADOW_H)
50 {
51 struct spwd *sp;
52 if ((sp = getspnam (id->username)) != NULL)
53 {
54 if (sp->sp_expire > 0 && time (NULL) > sp->sp_expire * 86400)
55 return -1;
56 encrypted_pass = sp->sp_pwdp;
57 }
58 }
59#endif
60
61 if (strcmp (crypt (passwd, encrypted_pass), encrypted_pass) == 0)
62 {
63 struct system_identity_data *data = xmalloc (sizeof (*data));
64 data->gid = pwd->pw_gid;
65 id->data = data;
66 return 0;
67 }
68 return -1;
69}
70
71static int
72system_is_group_member (pies_identity_provider_t provider,
73 pies_identity_t id, char * const * groups)
74{
75 struct system_identity_data *data = id->data;
76 struct group *gr;
77 int result = 0;
78
79 setgrent ();
80 while ((gr = getgrent ()))
81 {
82 char **p;
83
84 if (!is_array_member (groups, gr->gr_name))
85 continue;
86
87 if (gr->gr_gid == data->gid)
88 {
89 result = 1;
90 break;
91 }
92
93 for (p = gr->gr_mem; *p; p++)
94 if (strcmp (*p, id->username) == 0)
95 {
96 result = 1;
97 break;
98 }
99 }
100 endgrent ();
101 return result;
102}
103
104static void
105system_destroy_identity (pies_identity_provider_t p, pies_identity_t id)
106{
107 if (id->data)
108 free (id->data);
109}
110
111static void
112confhelp (void)
113{
114 static struct grecs_keyword kw[] = {
115 { "type", "'system", "Set mechanism type", grecs_type_null },
116 { NULL }
117 };
118
119 static struct grecs_keyword top[] = {
120 { "identity-provider", "name: string",
121 "Configuration for system identity provider",
122 grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL,
123 kw },
124 { NULL }
125 };
126 grecs_print_statement_array (top, 1, 0, stdout);
127}
128
129struct pies_identity_mechanism system_identity_mechanism = {
130 "system",
131 system_authenticate,
132 system_is_group_member,
133 system_destroy_identity,
134 NULL,
135 confhelp
136};
137
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
19noinst_HEADERS = libpies.h 19noinst_HEADERS = libpies.h
20 20
21libpies_a_SOURCES=\ 21libpies_a_SOURCES=\
22 arraymember.c\
22 parsetime.c\ 23 parsetime.c\
23 proctitle.c\ 24 proctitle.c\
24 strtotok.c 25 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 @@
1/* This file is part of GNU Pies.
2 Copyright (C) 2007, 2008, 2009, 2010, 2013 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <string.h>
21#include "libpies.h"
22
23int
24is_array_member (char * const * ar, char const *str)
25{
26 for (; *ar; ++ar)
27 {
28 if (strcmp (*ar, str) == 0)
29 return 1;
30 }
31 return 0;
32}
33
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,
56int strtotok (struct tokendef *tab, const char *str, int *pres); 56int strtotok (struct tokendef *tab, const char *str, int *pres);
57int strtotok_ci (struct tokendef *tab, const char *str, int *pres); 57int strtotok_ci (struct tokendef *tab, const char *str, int *pres);
58int toktostr (struct tokendef *tab, int tok, const char **pres); 58int toktostr (struct tokendef *tab, int tok, const char **pres);
59
60int is_array_member (char * const * ar, char const *str);
59 61
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
60cmdline.h: cmdline.opt 60cmdline.h: cmdline.opt
61 61
62LDADD = \ 62LDADD = \
63 ../ident/libident.a\
63 ../lib/libpies.a\ 64 ../lib/libpies.a\
64 @GRECS_LDADD@\ 65 @GRECS_LDADD@\
65 ../gnu/libgnu.a\ 66 ../gnu/libgnu.a\
66 $(MF_PROCTITLE_LIBS) 67 $(MF_PROCTITLE_LIBS)\
68 @PAM_LIBS@
67 69
68pkgstatedir=$(localstatedir)/pies 70pkgstatedir=$(localstatedir)/pies
69 71
70AM_CPPFLAGS=\ 72AM_CPPFLAGS=\
71 -I$(top_srcdir)/lib\ 73 -I$(top_srcdir)/lib\
74 -I$(top_srcdir)/ident\
72 -I$(top_srcdir)/gnu\ 75 -I$(top_srcdir)/gnu\
73 -I$(top_builddir)/gnu\ 76 -I$(top_builddir)/gnu\
74 @GRECS_INCLUDES@\ 77 @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
33 struct sockaddr sa; 33 struct sockaddr sa;
34}; 34};
35 35
36enum name_match
37 {
38 match_none,
39 match_user_name,
40 match_group_name
41 };
42
36struct acl_entry 43struct acl_entry
37{ 44{
38 grecs_locus_t locus; 45 grecs_locus_t locus;
39 int allow; 46 int allow;
40 int authenticated; 47 int authenticated;
41 pies_acl_t acl; 48 pies_acl_t acl;
42 struct grecs_list *groups; 49 enum name_match name_match;
50 char **names;
43 struct grecs_list *sockaddrs; 51 struct grecs_list *sockaddrs;
44}; 52};
45 53
@@ -53,14 +61,61 @@ struct pies_acl
53 61
54 62
55/* ACL creation */ 63/* ACL creation */
64void
65grecs_locus_point_copy (struct grecs_locus_point *dst,
66 struct grecs_locus_point *src)
67{
68 dst->file = grecs_strdup (src->file);
69 dst->line = src->line;
70 dst->col = src->col;
71}
72
73void
74grecs_locus_copy (struct grecs_locus *dst, struct grecs_locus *src)
75{
76 grecs_locus_point_copy (&dst->beg, &src->beg);
77 grecs_locus_point_copy (&dst->end, &src->end);
78}
79
80void
81grecs_locus_point_free (struct grecs_locus_point *p)
82{
83 grecs_free (p->file);
84}
85
86void
87grecs_locus_free (struct grecs_locus *loc)
88{
89 grecs_locus_point_free (&loc->beg);
90 grecs_locus_point_free (&loc->end);
91}
92
93static void
94acl_free_entry (void *p)
95{
96 struct acl_entry *ent = p;
97 pies_acl_free (ent->acl);
98 grecs_locus_free (&ent->locus);
99 grecs_list_free (ent->sockaddrs);
100 if (ent->names)
101 {
102 size_t i;
103
104 for (i = 0; ent->names[i]; i++)
105 free (ent->names[i]);
106 free (ent->names);
107 }
108 free (ent);
109}
56 110
57pies_acl_t 111pies_acl_t
58pies_acl_create (const char *name, grecs_locus_t *locus) 112pies_acl_create (const char *name, grecs_locus_t *locus)
59{ 113{
60 pies_acl_t acl = xmalloc (sizeof (acl[0])); 114 pies_acl_t acl = xmalloc (sizeof (acl[0]));
61 acl->name = name ? xstrdup (name) : NULL; 115 acl->name = name ? xstrdup (name) : NULL;
62 acl->locus = *locus; 116 grecs_locus_copy (&acl->locus, locus);
63 acl->list = grecs_list_create (); 117 acl->list = grecs_list_create ();
118 acl->list->free_entry = acl_free_entry;
64 return acl; 119 return acl;
65} 120}
66 121
@@ -68,6 +123,7 @@ void
68pies_acl_free (pies_acl_t acl) 123pies_acl_free (pies_acl_t acl)
69{ 124{
70 free (acl->name); 125 free (acl->name);
126 grecs_locus_free (&acl->locus);
71 grecs_list_free (acl->list); 127 grecs_list_free (acl->list);
72 free (acl); 128 free (acl);
73} 129}
@@ -196,6 +252,12 @@ _parse_sockaddr (struct acl_entry *entry, const grecs_value_t *value)
196 return 0; 252 return 0;
197} 253}
198 254
255static void
256sockaddr_free (void *p)
257{
258 free (p);
259}
260
199static int 261static int
200_parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv) 262_parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
201{ 263{
@@ -223,6 +285,7 @@ _parse_from (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
223 } 285 }
224 286
225 entry->sockaddrs = grecs_list_create (); 287 entry->sockaddrs = grecs_list_create ();
288 entry->sockaddrs->free_entry = sockaddr_free;
226 if (argv[0]->type == GRECS_TYPE_STRING) 289 if (argv[0]->type == GRECS_TYPE_STRING)
227 { 290 {
228 if (_parse_sockaddr (entry, argv[0])) 291 if (_parse_sockaddr (entry, argv[0]))
@@ -288,22 +351,38 @@ static int
288_parse_group (struct acl_entry *entry, size_t argc, grecs_value_t **argv) 351_parse_group (struct acl_entry *entry, size_t argc, grecs_value_t **argv)
289{ 352{
290 if (strcmp (argv[0]->v.string, "group") == 0) 353 if (strcmp (argv[0]->v.string, "group") == 0)
354 entry->name_match = match_group_name;
355 else if (strcmp (argv[0]->v.string, "user") == 0)
356 entry->name_match = match_user_name;
357 else
358 entry->name_match = match_none;
359
360 if (entry->name_match != match_none)
291 { 361 {
292 argc--; 362 argc--;
293 argv++; 363 argv++;
294 if (argc == 0) 364 if (argc == 0)
295 { 365 {
296 grecs_error (&entry->locus, 0, 366 grecs_error (&entry->locus, 0,
297 _("expected group list, but found end of statement")); 367 _("expected identity list, but found end of statement"));
298 return 1; 368 return 1;
299 } 369 }
300 if (argv[0]->type == GRECS_TYPE_STRING) 370 if (argv[0]->type == GRECS_TYPE_STRING)
301 { 371 {
302 entry->groups = grecs_list_create (); 372 entry->names = xcalloc (2, sizeof (entry->names[0]));
303 grecs_list_append (entry->groups, xstrdup (argv[0]->v.string)); 373 entry->names[0] = xstrdup (argv[0]->v.string);
374 entry->names[1] = NULL;
304 } 375 }
305 else 376 else
306 entry->groups = argv[0]->v.list; 377 {
378 size_t i;
379 struct grecs_list_entry *ep;
380 entry->names = xcalloc (argv[0]->v.list->count + 1,
381 sizeof (entry->names[0]));
382 for (i = 0, ep = argv[0]->v.list->head; ep; ep = ep->next, ++i)
383 entry->names[i] = xstrdup (ep->data);
384 entry->names[i] = NULL;
385 }
307 argc--; 386 argc--;
308 argv++; 387 argv++;
309 } 388 }
@@ -327,29 +406,30 @@ parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl,
327{ 406{
328 struct acl_entry *entry = xzalloc (sizeof (*entry)); 407 struct acl_entry *entry = xzalloc (sizeof (*entry));
329 408
330 entry->locus = *locus; 409 grecs_locus_copy (&entry->locus, locus);
331 entry->allow = allow; 410 entry->allow = allow;
332 411
333 switch (value->type) 412 if (value)
334 { 413 switch (value->type)
335 case GRECS_TYPE_STRING: 414 {
336 if (_parse_token (entry, value)) 415 case GRECS_TYPE_STRING:
337 { 416 if (_parse_token (entry, value))
338 grecs_error (&entry->locus, 0, _("unknown word `%s'"), 417 {
339 value->v.string); 418 grecs_error (&entry->locus, 0, _("unknown word `%s'"),
419 value->v.string);
420 return 1;
421 }
422 break;
423
424 case GRECS_TYPE_ARRAY:
425 if (_parse_acl (entry, value->v.arg.c, value->v.arg.v))
340 return 1; 426 return 1;
341 } 427 break;
342 break; 428
343 429 case GRECS_TYPE_LIST:
344 case GRECS_TYPE_ARRAY: 430 grecs_error (locus, 0, _("unexpected list"));
345 if (_parse_acl (entry, value->v.arg.c, value->v.arg.v))
346 return 1; 431 return 1;
347 break; 432 }
348
349 case GRECS_TYPE_LIST:
350 grecs_error (locus, 0, _("unexpected list"));
351 return 1;
352 }
353 grecs_list_append (acl->list, entry); 433 grecs_list_append (acl->list, entry);
354 return 0; 434 return 0;
355} 435}
@@ -480,12 +560,12 @@ deny_cb (enum grecs_callback_command cmd,
480 560
481struct grecs_keyword acl_keywords[] = { 561struct grecs_keyword acl_keywords[] = {
482 /* TRANSLATORS: only words within angle brackets are translatable */ 562 /* TRANSLATORS: only words within angle brackets are translatable */
483 { "allow", N_("[all|authenticated|group <grp: list>] [from <addr: list>]"), 563 { "allow", N_("[all|authenticated|user <usr: list>|group <grp: list>] [from <addr: list>]"),
484 N_("Allow access"), 564 N_("Allow access"),
485 grecs_type_string, GRECS_MULT, NULL, 0, 565 grecs_type_string, GRECS_MULT, NULL, 0,
486 allow_cb }, 566 allow_cb },
487 /* TRANSLATORS: only words within angle brackets are translatable */ 567 /* TRANSLATORS: only words within angle brackets are translatable */
488 { "deny", N_("[all|authenticated|group <grp: list>] [from <addr: list>]"), 568 { "deny", N_("[all|authenticated|user <usr: list>|group <grp: list>] [from <addr: list>]"),
489 N_("Deny access"), 569 N_("Deny access"),
490 grecs_type_string, GRECS_MULT, NULL, 0, 570 grecs_type_string, GRECS_MULT, NULL, 0,
491 deny_cb }, 571 deny_cb },
@@ -534,32 +614,30 @@ _check_sockaddr (struct pies_sockaddr *sptr, struct acl_input *input)
534} 614}
535 615
536static int 616static int
537match_group (const char **groups, const char *arg)
538{
539 for (; *groups; groups++)
540 if (strcmp (*groups, arg) == 0)
541 return 1;
542 return 0;
543}
544
545static int
546_acl_check (struct acl_entry *ent, struct acl_input *input) 617_acl_check (struct acl_entry *ent, struct acl_input *input)
547{ 618{
548 int result = 1; 619 int result = 1;
549 620
550 if (ent->authenticated) 621 if (ent->authenticated)
551 { 622 {
552 result = input->user != NULL; 623 result = input->identity != NULL;
553 if (!result) 624 if (!result)
554 return result; 625 return result;
555 } 626 }
556 627
557 if (ent->groups) 628 switch (ent->name_match)
558 { 629 {
559 struct grecs_list_entry *ep; 630 case match_none:
631 break;
560 632
561 for (ep = ent->groups->head; result && ep; ep = ep->next) 633 case match_user_name:
562 result = match_group (input->groups, ep->data); 634 result = pies_identity_is_user (input->identity, ent->names);
635 if (!result)
636 return result;
637 break;
638
639 case match_group_name:
640 result = pies_identity_is_group_member (input->identity, ent->names);
563 if (!result) 641 if (!result)
564 return result; 642 return result;
565 } 643 }
@@ -646,7 +724,7 @@ acl_copy (void *a, void *b)
646} 724}
647 725
648static void 726static void
649acl_free_entry (void *p) 727acl_free (void *p)
650{ 728{
651 pies_acl_free (p); 729 pies_acl_free (p);
652} 730}
@@ -664,7 +742,7 @@ pies_acl_install (pies_acl_t acl)
664 acl_compare, 742 acl_compare,
665 acl_copy, 743 acl_copy,
666 NULL, 744 NULL,
667 acl_free_entry); 745 acl_free);
668 if (!acl_table) 746 if (!acl_table)
669 xalloc_die (); 747 xalloc_die ();
670 } 748 }
diff --git a/src/acl.h b/src/acl.h
index dc09d7b..757104d 100644
--- a/src/acl.h
+++ b/src/acl.h
@@ -21,11 +21,11 @@ struct acl_input
21{ 21{
22 struct sockaddr *addr; 22 struct sockaddr *addr;
23 socklen_t addrlen; 23 socklen_t addrlen;
24 const char *user; 24 pies_identity_t identity;
25 const char **groups;
26}; 25};
27 26
28pies_acl_t pies_acl_create (const char *name, grecs_locus_t *locus); 27pies_acl_t pies_acl_create (const char *name, grecs_locus_t *locus);
28void pies_acl_free (pies_acl_t acl);
29int pies_acl_check (pies_acl_t acl, struct acl_input *input, int result); 29int pies_acl_check (pies_acl_t acl, struct acl_input *input, int result);
30int parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl, 30int parse_acl_line (grecs_locus_t *locus, int allow, pies_acl_t acl,
31 grecs_value_t *value); 31 grecs_value_t *value);
diff --git a/src/ctl.c b/src/ctl.c
index f9f2d76..20c16e1 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -17,11 +17,14 @@
17#include "pies.h" 17#include "pies.h"
18#include "prog.h" 18#include "prog.h"
19#include "xvasprintf.h" 19#include "xvasprintf.h"
20#include "identity.h"
20 21
21#define DEFAULT_CONTROL_URL "unix:///tmp/%s.ctl" 22#define DEFAULT_CONTROL_URL "unix:///tmp/%s.ctl"
22 23
23struct control control; 24struct control control;
24 25
26pies_identity_t identity;
27
25 28
26struct ctlbuf 29struct ctlbuf
27{ 30{
@@ -107,6 +110,7 @@ ctlbuf_chomp (struct ctlbuf *buf)
107 110
108struct ctlio; 111struct ctlio;
109 112
113static void cmd_auth (struct ctlio *, size_t, char **);
110static void cmd_quit (struct ctlio *, size_t, char **); 114static void cmd_quit (struct ctlio *, size_t, char **);
111static void cmd_noop (struct ctlio *, size_t, char **); 115static void cmd_noop (struct ctlio *, size_t, char **);
112static void cmd_help (struct ctlio *, size_t, char **); 116static void cmd_help (struct ctlio *, size_t, char **);
@@ -129,6 +133,8 @@ struct ctlio_command
129}; 133};
130 134
131static struct ctlio_command cmdtab[] = { 135static struct ctlio_command cmdtab[] = {
136 { "auth", "authenticate",
137 CTL_INITIAL_STATE, 3, 3, cmd_auth },
132 { "noop", "no operation", 138 { "noop", "no operation",
133 CTL_ALL_STATES, 1, 1, cmd_noop }, 139 CTL_ALL_STATES, 1, 1, cmd_noop },
134 { "id", "identify the instance", 140 { "id", "identify the instance",
@@ -167,6 +173,8 @@ ctlio_command_find (char const *verb)
167 173
168struct ctlio 174struct ctlio
169{ 175{
176 union pies_sockaddr_storage addr;
177 socklen_t addrlen;
170 int state; 178 int state;
171 int action; 179 int action;
172 struct ctlbuf ibuf; 180 struct ctlbuf ibuf;
@@ -181,7 +189,8 @@ ctlio_create (void)
181 struct ctlio *io; 189 struct ctlio *io;
182 190
183 io = xmalloc (sizeof (*io)); 191 io = xmalloc (sizeof (*io));
184 io->state = CTL_AUTHENTICATED_STATE; //FIXME CTL_INITIAL_STATE; 192 io->state = identity_provider_list
193 ? CTL_INITIAL_STATE : CTL_AUTHENTICATED_STATE;
185 io->action = ACTION_CONT; 194 io->action = ACTION_CONT;
186 ctlbuf_init (&io->ibuf); 195 ctlbuf_init (&io->ibuf);
187 ctlbuf_init (&io->obuf); 196 ctlbuf_init (&io->obuf);
@@ -308,12 +317,56 @@ static void
308ctlio_initial_reply (struct ctlio *io) 317ctlio_initial_reply (struct ctlio *io)
309{ 318{
310 ctlio_printf (io, "220 %s", instance); 319 ctlio_printf (io, "220 %s", instance);
311 ctlio_printf (io, " <%s>", "foobarbaz");
312 //FIXME: auth mechanisms 320 //FIXME: auth mechanisms
313 ctlio_eol (io); 321 ctlio_eol (io);
314} 322}
315 323
316static void 324static void
325cmd_auth (struct ctlio *io, size_t argc, char **argv)
326{
327 struct grecs_list_entry *ep;
328 pies_identity_t id = pies_identity_create (argv[1]);
329 int auth = 0;
330
331 for (ep = identity_provider_list->head; ep; ep = ep->next)
332 {
333 pies_identity_provider_t provider = ep->data;
334 char const *pname = pies_identity_provider_name (provider);
335
336 debug(1, ("trying %s...", pname));
337 if (pies_authenticate (provider, id, argv[2]) == 0)
338 {
339 if (check_acl (control.id_acl,
340 (struct sockaddr *)&io->addr, io->addrlen, id))
341 {
342 logmsg (LOG_AUTH, "%s authenticated via %s, but failed ACL check",
343 argv[1], pname);
344 auth = 0;
345 }
346 else
347 {
348 logmsg (LOG_AUTH, "%s authenticated via %s",
349 argv[1], pname);
350 auth = 1;
351 }
352 break;
353 }
354 }
355
356 if (auth)
357 {
358 ctlio_reply (io, "230", "authentication successful");
359 identity = id;
360 io->state = CTL_AUTHENTICATED_STATE;
361 }
362 else
363 {
364 pies_identity_destroy (id);
365 ctlio_reply (io, "531", "access denied");
366 }
367}
368
369static void
317cmd_noop (struct ctlio *io, size_t argc, char **argv) 370cmd_noop (struct ctlio *io, size_t argc, char **argv)
318{ 371{
319 ctlio_reply (io, "220", "%s attending", instance); 372 ctlio_reply (io, "220", "%s attending", instance);
@@ -347,8 +400,11 @@ cmd_help (struct ctlio *io, size_t argc, char **argv)
347 ctlio_reply (io, "113", "help text follows"); 400 ctlio_reply (io, "113", "help text follows");
348 for (cp = cmdtab; cp->verb; cp++) 401 for (cp = cmdtab; cp->verb; cp++)
349 { 402 {
350 ctlio_printf (io, "%-9s%s", cp->verb, cp->descr); 403 if (cp->states & io->state)
351 ctlio_eol (io); 404 {
405 ctlio_printf (io, "%-9s%s", cp->verb, cp->descr);
406 ctlio_eol (io);
407 }
352 } 408 }
353 ctlio_eot (io); 409 ctlio_eot (io);
354} 410}
@@ -1000,7 +1056,7 @@ ctl_accept (int socket, void *data)
1000 free (s); 1056 free (s);
1001 } 1057 }
1002 1058
1003 if (check_acl (control.acl, (struct sockaddr *)&addr, addrlen)) 1059 if (check_acl (control.conn_acl, (struct sockaddr *)&addr, addrlen, NULL))
1004 { 1060 {
1005 close (fd); 1061 close (fd);
1006 return 1; 1062 return 1;
@@ -1008,6 +1064,8 @@ ctl_accept (int socket, void *data)
1008 /* FIXME: Check number of connections? */ 1064 /* FIXME: Check number of connections? */
1009 1065
1010 io = ctlio_create (); 1066 io = ctlio_create ();
1067 io->addr = addr;
1068 io->addrlen = addrlen;
1011 ctlio_initial_reply (io); 1069 ctlio_initial_reply (io);
1012 register_socket (fd, NULL, ctlwr, NULL, io); 1070 register_socket (fd, NULL, ctlwr, NULL, io);
1013 1071
diff --git a/src/inetd-bi.c b/src/inetd-bi.c
index e472390..de9cfa0 100644
--- a/src/inetd-bi.c
+++ b/src/inetd-bi.c
@@ -357,7 +357,7 @@ tcpmux (int fd, struct component const *comp)
357 return; 357 return;
358 } 358 }
359 359
360 if (check_acl (comp->acl, (struct sockaddr *) &sa, salen)) 360 if (check_acl (comp->acl, (struct sockaddr *) &sa, salen, NULL))
361 { 361 {
362 fd_report (fd, "-Service not available\r\n"); 362 fd_report (fd, "-Service not available\r\n");
363 return; 363 return;
diff --git a/src/pies.c b/src/pies.c
index 696e9f0..9f5f174 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -18,6 +18,7 @@
18#include <locale.h> 18#include <locale.h>
19#include <configmake.h> 19#include <configmake.h>
20#include "meta1lex.h" 20#include "meta1lex.h"
21#include "identity.h"
21 22
22int preprocess_only; /* Preprocess config, do nothing more */ 23int preprocess_only; /* Preprocess config, do nothing more */
23int lint_mode; /* Test configuration syntax and exit */ 24int lint_mode; /* Test configuration syntax and exit */
@@ -1541,9 +1542,15 @@ struct grecs_keyword control_keywords[] = {
1541 &control.url, 0, _cb_url}, 1542 &control.url, 0, _cb_url},
1542 {"acl", 1543 {"acl",
1543 N_("name: string"), 1544 N_("name: string"),
1544 N_("Set ACL."), 1545 N_("Set connection ACL."),
1546 grecs_type_section, GRECS_DFLT,
1547 &control.conn_acl, 0,
1548 acl_section_parser, NULL, acl_keywords},
1549 {"identity-acl",
1550 N_("name: string"),
1551 N_("Set identity ACL."),
1545 grecs_type_section, GRECS_DFLT, 1552 grecs_type_section, GRECS_DFLT,
1546 &control.acl, 0, 1553 &control.id_acl, 0,
1547 acl_section_parser, NULL, acl_keywords}, 1554 acl_section_parser, NULL, acl_keywords},
1548 {"idle-timeout", 1555 {"idle-timeout",
1549 "n", 1556 "n",
@@ -1760,6 +1767,8 @@ struct grecs_keyword pies_keywords[] = {
1760 &mailer_command_line, 0, 1767 &mailer_command_line, 0,
1761 NULL 1768 NULL
1762 }, 1769 },
1770 { "identity-provider", "name: string", "Configure identity provider",
1771 grecs_type_section, GRECS_INAC | GRECS_HIDDEN },
1763 {NULL} 1772 {NULL}
1764}; 1773};
1765 1774
@@ -1775,6 +1784,39 @@ config_init ()
1775 obstack_grow (&pp_stk, DEFAULT_PREPROCESSOR, 1784 obstack_grow (&pp_stk, DEFAULT_PREPROCESSOR,
1776 sizeof (DEFAULT_PREPROCESSOR) - 1); 1785 sizeof (DEFAULT_PREPROCESSOR) - 1);
1777 } 1786 }
1787 pies_identity_mechanism_register (&system_identity_mechanism);
1788#ifdef WITH_PAM
1789 pies_identity_mechanism_register (&pam_identity_mechanism);
1790#endif
1791}
1792
1793static void
1794config_error ()
1795{
1796 if (!init_process)
1797 exit (EX_CONFIG);
1798}
1799
1800void
1801config_parse (char const *name)
1802{
1803 struct grecs_node *node;
1804 struct grecs_node *tree = grecs_parse (name);
1805 if (!tree)
1806 config_error ();
1807
1808 for (node = tree; node; node = node->next)
1809 {
1810 node = grecs_find_node (node, "identity-provider");
1811 if (!node)
1812 break;
1813 pies_config_provider (node);
1814 }
1815
1816 if (grecs_tree_process (tree, pies_keywords))
1817 config_error ();
1818
1819 grecs_tree_free (tree);
1778} 1820}
1779 1821
1780void 1822void
@@ -1786,6 +1828,7 @@ config_help ()
1786 "For more information, use `info pies configuration'."); 1828 "For more information, use `info pies configuration'.");
1787 grecs_print_docstring (docstring, 0, stdout); 1829 grecs_print_docstring (docstring, 0, stdout);
1788 grecs_print_statement_array (pies_keywords, 1, 0, stdout); 1830 grecs_print_statement_array (pies_keywords, 1, 0, stdout);
1831 pies_config_identity_mechanisms_help ();
1789} 1832}
1790 1833
1791static enum config_syntax current_syntax = CONF_PIES; 1834static enum config_syntax current_syntax = CONF_PIES;
@@ -2241,13 +2284,6 @@ set_state_file_names (const char *base)
2241 qotdfile = mkfilename (statedir, base, ".qotd"); 2284 qotdfile = mkfilename (statedir, base, ".qotd");
2242} 2285}
2243 2286
2244static void
2245config_error ()
2246{
2247 if (!init_process)
2248 exit (EX_CONFIG);
2249}
2250
2251int 2287int
2252main (int argc, char **argv) 2288main (int argc, char **argv)
2253{ 2289{
@@ -2367,13 +2403,8 @@ main (int argc, char **argv)
2367 switch (file->syntax) 2403 switch (file->syntax)
2368 { 2404 {
2369 case CONF_PIES: 2405 case CONF_PIES:
2370 { 2406 config_parse (file->name);
2371 struct grecs_node *tree = grecs_parse (file->name); 2407 break;
2372 if (!tree || grecs_tree_process (tree, pies_keywords))
2373 config_error ();
2374 grecs_tree_free (tree);
2375 break;
2376 }
2377 2408
2378 case CONF_INETD: 2409 case CONF_INETD:
2379 if (inetd_parse_conf (file->name)) 2410 if (inetd_parse_conf (file->name))
diff --git a/src/pies.h b/src/pies.h
index 82ffddb..3919703 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -58,6 +58,7 @@
58#include "quotearg.h" 58#include "quotearg.h"
59#include "fprintftime.h" 59#include "fprintftime.h"
60 60
61#include "identity.h"
61#include "acl.h" 62#include "acl.h"
62#include "libpies.h" 63#include "libpies.h"
63 64
@@ -338,7 +339,8 @@ void progman_iterate_comp (int (*fun) (struct component *, void *),
338 339
339void fd_report (int fd, const char *msg); 340void fd_report (int fd, const char *msg);
340 341
341int check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen); 342int check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
343 pies_identity_t identity);
342 344
343void log_setup (int want_stderr); 345void log_setup (int want_stderr);
344void signal_setup (RETSIGTYPE (*sf)(int)); 346void signal_setup (RETSIGTYPE (*sf)(int));
@@ -561,7 +563,8 @@ void sysvinit_acct (int what, const char *user, const char *id, pid_t pid,
561struct control 563struct control
562{ 564{
563 struct pies_url *url; 565 struct pies_url *url;
564 pies_acl_t acl; 566 pies_acl_t conn_acl;
567 pies_acl_t id_acl;
565 unsigned int idle_timeout; 568 unsigned int idle_timeout;
566}; 569};
567 570
diff --git a/src/progman.c b/src/progman.c
index 12969ab..1ec5a8d 100644
--- a/src/progman.c
+++ b/src/progman.c
@@ -1301,7 +1301,8 @@ prog_start (struct prog *prog)
1301} 1301}
1302 1302
1303int 1303int
1304check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen) 1304check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen,
1305 pies_identity_t identity)
1305{ 1306{
1306 struct acl_input input; 1307 struct acl_input input;
1307 int rc; 1308 int rc;
@@ -1311,8 +1312,7 @@ check_acl (pies_acl_t acl, struct sockaddr *s, socklen_t salen)
1311 1312
1312 input.addr = s; 1313 input.addr = s;
1313 input.addrlen = salen; 1314 input.addrlen = salen;
1314 input.user = NULL; 1315 input.identity = identity;
1315 input.groups = NULL;
1316 1316
1317 rc = pies_acl_check (acl, &input, 1); 1317 rc = pies_acl_check (acl, &input, 1);
1318 if (rc == 0) 1318 if (rc == 0)
@@ -1374,8 +1374,8 @@ _prog_accept (struct prog *p)
1374 free (s); 1374 free (s);
1375 } 1375 }
1376 1376
1377 if (check_acl (p->v.p.comp->acl, (struct sockaddr *)&addr, addrlen) 1377 if (check_acl (p->v.p.comp->acl, (struct sockaddr *)&addr, addrlen, NULL)
1378 || check_acl (pies_acl, (struct sockaddr *)&addr, addrlen)) 1378 || check_acl (pies_acl, (struct sockaddr *)&addr, addrlen, NULL))
1379 { 1379 {
1380 fd_report (fd, p->v.p.comp->access_denied_message); 1380 fd_report (fd, p->v.p.comp->access_denied_message);
1381 close (fd); 1381 close (fd);

Return to:

Send suggestions and report system problems to the System administrator.