diff options
Diffstat (limited to 'ident/system.c')
-rw-r--r-- | ident/system.c | 137 |
1 files changed, 137 insertions, 0 deletions
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 +}; + |