diff options
author | Arun Scaria <arunscaria91@gmail.com> | 2011-06-22 13:48:18 +0530 |
---|---|---|
committer | Arun Scaria <arunscaria91@gmail.com> | 2011-06-22 13:48:18 +0530 |
commit | 9be6ed2d662d57e7d595714aa85126a84727e49b (patch) | |
tree | 98c223d1cd1270c568e53338c114342f38184f76 /src | |
parent | fe8426ea00e7cf6194f0fab9606b3937c4ea3344 (diff) | |
download | sssd_unused-9be6ed2d662d57e7d595714aa85126a84727e49b.tar.gz sssd_unused-9be6ed2d662d57e7d595714aa85126a84727e49b.tar.xz sssd_unused-9be6ed2d662d57e7d595714aa85126a84727e49b.zip |
New Make + new plugin code
Diffstat (limited to 'src')
-rw-r--r-- | src/responder/sudo/sudosrv.c | 95 | ||||
-rw-r--r-- | src/sss_client/sudo_plugin/README | 52 | ||||
-rw-r--r-- | src/sss_client/sudo_plugin/missing.h | 48 | ||||
-rw-r--r-- | src/sss_client/sudo_plugin/sss_sudo_cli.h | 89 | ||||
-rw-r--r-- | src/sss_client/sudo_plugin/sss_sudoplugin.c | 1265 |
5 files changed, 1549 insertions, 0 deletions
diff --git a/src/responder/sudo/sudosrv.c b/src/responder/sudo/sudosrv.c new file mode 100644 index 00000000..6353fd72 --- /dev/null +++ b/src/responder/sudo/sudosrv.c @@ -0,0 +1,95 @@ +/* + SSSD + + SUDO Responder + + Copyright (C) Arun Scaria <arunscaria91@gmail.com> (2011) + + 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/>. +*/ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <string.h> +#include <sys/time.h> +#include <errno.h> + +#include <popt.h> +#include "util/util.h" + + +#define CONFDB_SUDO_CONF_ENTRY "config/sudo" + + +int sudo_process_init(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct confdb_ctx *cdb) +{ + return EOK; +} + +int main(int argc, const char *argv[]) +{ + int opt; + poptContext pc; + struct main_context *main_ctx; + int ret; + + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_MAIN_OPTS + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + + poptFreeContext(pc); + + /* set up things like debug, signals, daemonization, etc... */ + debug_log_file = "sssd_sudo_dbg"; + + ret = server_setup("sssd[sudo]", 0, CONFDB_SUDO_CONF_ENTRY, &main_ctx); + if (ret != EOK) return 2; + + ret = die_if_parent_died(); + if (ret != EOK) { + /* This is not fatal, don't return */ + DEBUG(2, ("Could not set up to exit when parent process does\n")); + } + + ret = sudo_process_init(main_ctx, + main_ctx->event_ctx, + main_ctx->confdb_ctx); + if (ret != EOK) return 3; + + /* loop on main */ + server_loop(main_ctx); + + return 0; +} + diff --git a/src/sss_client/sudo_plugin/README b/src/sss_client/sudo_plugin/README new file mode 100644 index 00000000..fea5565f --- /dev/null +++ b/src/sss_client/sudo_plugin/README @@ -0,0 +1,52 @@ + + SSSD SUDO - System Security Services Daemon SU Do + -------------------------------------------------- + + Introduction + ------------ + SSSD provides a set of daemons to manage access to remote directories and + authentication mechanisms such as LDAP, Kerberos or FreeIPA. It provides + an NSS and PAM interface toward the system and a pluggable backend system + to connect to multiple different account sources. SSSD SUDO project is a + plugin based system that gives the power of implemnting sudo rules into an + ldap server and authenticates users based on these sudo rules with the help + of cached credentials of SSSD. It is a helpful tool to create new access + policies and to implment it to wide range of users with common LDAP repository + that stores these rules. Sice it is a plugin based system you can plu-in/unplug + it to the sudo utility. This project is under the Google summer of code 2011. + + More information about SSSD can be found on its project page - + <http://fedorahosted.org/sssd/> + + Building and installation + ------------------------- + Please see the file BUILD.txt for details + + Documentation + ------------- + The most up-to-date documentation can be found at + <http://fedorahosted.org/sssd/wiki/HOWTO_Configure> + + Licensing + --------- + Please see the file called COPYING. + + Contacts + -------- + There are several ways to contact us: + + * the sssd-devel mailing list: + <https://fedorahosted.org/mailman/listinfo/sssd-devel> + + * the #freeipa IRC channel on freenode: + irc://irc.freenode.net/freeipa + + * Author: Arun Scaria ( r00tkit ) + email: arunscaria91@gmail.com + + * Mentor: Stephen Gallagher + email: sgallagh@redhat.com + + * Mentor: JrAquino + email: jr.aquino@citrix.com + diff --git a/src/sss_client/sudo_plugin/missing.h b/src/sss_client/sudo_plugin/missing.h new file mode 100644 index 00000000..ee090c59 --- /dev/null +++ b/src/sss_client/sudo_plugin/missing.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1996, 1998-2005, 2008, 2009-2010 + * Todd C. Miller <Todd.Miller@courtesan.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#ifndef _SUDO_MISSING_H +#define _SUDO_MISSING_H + +#include <stdio.h> +#include <stdarg.h> + +/* + * Macros and functions that may be missing on some operating systems. + */ + + +/* + * If we lack getprogname(), emulate with __progname if possible. + * Otherwise, add a prototype for use with our own getprogname.c. + */ +#ifndef HAVE_GETPROGNAME +# ifdef HAVE___PROGNAME +extern const char *__progname; +# define getprogname() (__progname) +# else +const char *getprogname(void); +void setprogname(const char *); +#endif /* HAVE___PROGNAME */ +#endif /* !HAVE_GETPROGNAME */ + + +#endif /* _SUDO_MISSING_H */ diff --git a/src/sss_client/sudo_plugin/sss_sudo_cli.h b/src/sss_client/sudo_plugin/sss_sudo_cli.h new file mode 100644 index 00000000..76dc242f --- /dev/null +++ b/src/sss_client/sudo_plugin/sss_sudo_cli.h @@ -0,0 +1,89 @@ +/* + SSSD + + sss_sudo_cli.h + + Authors: + Arun Scaria <arunscaria91@gmail.com> + + Copyright (C) 2011 Red Hat + + 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/> +*/ + +#ifndef _SSS_SUDO_CLI_H_ +#define _SSS_SUDO_CLI_H_ + + +#undef SSS_END_OF_SUDO_REQUEST +#define SSS_END_OF_SUDO_REQUEST 0x405645 + +#undef SSS_START_OF_SUDO_REQUEST +#define SSS_START_OF_SUDO_REQUEST 0x436789 + + +#ifndef _SSSCLI_H + + /* If sss_cli.h is not imported */ +struct sss_cli_req_data { + size_t len; + const void *data; +}; + +enum sss_status { + SSS_STATUS_TRYAGAIN, + SSS_STATUS_UNAVAIL, + SSS_STATUS_SUCCESS +}; + +#endif + +enum error_types_sudo{ + + SSS_SUDO_SUCCESS = 0x01, + SSS_SUDO_BUF_ERR, + SSS_SUDO_SYSTEM_ERR, + SSS_SUDO_LOG_ERR, + SSS_SUDO_LOG_NOTICE, + +}; + + + +enum sudo_item_type{ + + SSS_SUDO_ITEM_UID = 0x0000, + SSS_SUDO_ITEM_CWD, + SSS_SUDO_ITEM_TTY, + SSS_SUDO_ITEM_RUSER, + SSS_SUDO_ITEM_RGROUP, + SSS_SUDO_ITEM_PROMPT, + SSS_SUDO_ITEM_NETADDR, + SSS_SUDO_ITEM_USE_SUDOEDIT, + SSS_SUDO_ITEM_USE_SETHOME, + SSS_SUDO_ITEM_USE_PRESERV_ENV, + SSS_SUDO_ITEM_USE_IMPLIED_SHELL, + SSS_SUDO_ITEM_USE_LOGIN_SHELL, + SSS_SUDO_ITEM_USE_RUN_SHELL, + SSS_SUDO_ITEM_USE_PRE_GROUPS, + SSS_SUDO_ITEM_USE_IGNORE_TICKET, + SSS_SUDO_ITEM_USE_NON_INTERACTIVE, + SSS_SUDO_ITEM_DEBUG_LEVEL, + SSS_SUDO_ITEM_COMMAND, + SSS_SUDO_ITEM_USER_ENV, + SSS_SUDO_ITEM_CLI_PID + +}; + +#endif /* _SSS_SUDO_CLI_H_ */ diff --git a/src/sss_client/sudo_plugin/sss_sudoplugin.c b/src/sss_client/sudo_plugin/sss_sudoplugin.c new file mode 100644 index 00000000..54bdbc8e --- /dev/null +++ b/src/sss_client/sudo_plugin/sss_sudoplugin.c @@ -0,0 +1,1265 @@ +/* + SSSD + + sss_sudo_plugin.c + + Authors: + Arun Scaria <arunscaria91@gmail.com> + + Copyright (C) 2011 Red Hat + + 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/> + + ----------------TO DO--------------------- + Create/Edit /etc/sudo.conf as below. + --/etc/sudo.conf-- + # Default /etc/sudo.conf file + # + # Format: + # Plugin plugin_name plugin_path + # Path askpass /path/to/askpass + # + # The plugin_path is relative to /usr/local/libexec unless + # fully qualified. + # The plugin_name corresponds to a global symbol in the plugin + # that contains the plugin interface structure. + # + Plugin sss_sudo_policy libsss_sudoplugin.so + + +*/ + + /* + * Define to the version of sudo package + * This declaration is to be removed and + * it is to be imported from config.h + */ +#define SUDO_PACKAGE_STRING "sudo 1.8.1" + +#ifndef _PATH_VI +#define _PATH_VI "/bin/vi" +#endif + +#ifndef _PATH_DEFPATH +/* Default path to executables */ +#define _PATH_DEFPATH "/usr/bin:/bin" +#endif + + +#include "config.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <stdint.h> + +#include <stdio.h> +#ifdef STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif /* STDC_HEADERS */ + + +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include <memory.h> +# endif +# include <string.h> +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include <strings.h> +#endif /* HAVE_STRINGS_H */ + + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif /* HAVE_UNISTD_H */ +#include <ctype.h> +#include <fcntl.h> +#include <limits.h> +#include <grp.h> +#include <pwd.h> +#include <stdarg.h> + +#include "missing.h" +#include <sudo_plugin.h> + + +#include <security/pam_appl.h> +#include <security/pam_misc.h> + +#include <dbus/dbus.h> + +#include "sss_sudo_cli.h" + + + + +#ifdef __TANDEM +/* If it is a tandem system */ +# define ROOT_UID 65535 +#else +/* If it is a normal system */ +# define ROOT_UID 0 +#endif + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 +#undef ERROR +#define ERROR -1 + +#undef SSS_SUDO_PLUGIN_VERSION +#define SSS_SUDO_PLUGIN_VERSION "1.0.0" + +#undef SSS_SUDO_IO_PLUGIN_VERSION +#define SSS_SUDO_IO_PLUGIN_VERSION "1.0.0" + + +#undef SSS_SUDO_PAM_SERVICE +#define SSS_SUDO_PAM_SERVICE "sudo" + + +#define CHECK_AND_RETURN_BOOL_STRING(obj) ((obj)?"FALSE":"TRUE") + +static struct plugin_state { + char **envp; + char * const *settings; + char * const *user_info; +} plugin_state; +static sudo_conv_t sudo_conv; +static sudo_printf_t sudo_log; +static uid_t runas_uid = ROOT_UID; +static gid_t runas_gid = -1; +static int use_sudoedit; +static int debug_level; + +/* + * user_info_struct strucure stores the user info. The lines and cols are + * number of columns and lines user terminal supports. Most + * probably it can be avoided. But I'm keeping it till the final + * code. + */ + +static struct user_info_struct +{ +char *username; +int lines; +int cols; +}user_information; + + +/* The sss_sudo_msg_contents have the message components to be + * passed to SSSD responder. + */ + +static struct sss_sudo_msg_contents +{ + + /* from user_info */ + uid_t userid; + char *cwd; + char *tty; + + size_t cwd_size; + size_t tty_size; + + /* from settings */ + char * runas_user; + char * runas_group; + char * prompt; + char * network_addrs; + int use_sudoedit; + int use_set_home; + int use_preserve_environment; + int use_implied_shell; + int use_login_shell; + int use_run_shell; + int use_preserve_groups; + int use_ignore_ticket; + int use_noninteractive; + int debug_level; + + size_t runas_user_size; + size_t runas_group_size; + size_t prompt_size; + size_t network_addrs_size; + + /*from user_env*/ + char * const * user_env; + size_t user_env_size; + + /* command with arguments */ + char * command; + size_t command_size; + + /* Clients pid */ + int cli_pid; +}msg; + + + + +static struct pam_conv conv = { + misc_conv, + NULL +}; + + + + + +static void print_sudo_items() +{ + if (msg.userid < 0) return; + D(("Sending data to sssd:: ")); + D(("UserID: %d", msg.userid)); + D(("TTY: %s", CHECK_AND_RETURN_PI_STRING(msg.tty))); + D(("CWD: %s", CHECK_AND_RETURN_PI_STRING(msg.cwd))); + D(("Run as user: %s", CHECK_AND_RETURN_PI_STRING(msg.runas_user))); + D(("Run as group: %s", CHECK_AND_RETURN_PI_STRING(msg.runas_group))); + D(("Prompt: %s", CHECK_AND_RETURN_PI_STRING(msg.prompt))); + D(("Network Address: %s",CHECK_AND_RETURN_PI_STRING(msg.network_addrs))); + D(("Use sudo edit: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_sudoedit))); + D(("Use set home: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_set_home))); + D(("Use preserve environment: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_preserver_environment))); + D(("Use implied shell: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_implied_shell))); + D(("Use login shell: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_login_shell))); + D(("Use run shell: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_run_shell))); + D(("Use preserve groups: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_preserve_groups))); + D(("Use ignore ticket: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_ignore_ticket))); + D(("Use non interactive mode: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_noninteractive))); + D(("Use debug level: %s",CHECK_AND_RETURN_BOOL_STRING(msg.use_sudoedit))); + D(("Command: %s", CHECK_AND_RETURN_PI_STRING(msg.command))); + /* add env var list */ + D(("Cli_PID: %d", msg.cli_pid)); +} + + + +/* initialise size of message contents as zero and boolean values as FALSE */ +static void init_size_of_msg_contents() +{ + msg.userid=-1; + msg.cwd_size = 0; + msg.tty_size= 0; + + + msg.use_sudoedit = FALSE; + msg.use_set_home = FALSE; + msg.use_preserve_environment = FALSE; + msg.use_implied_shell = FALSE; + msg.use_login_shell = FALSE; + msg.use_run_shell = FALSE; + msg.use_preserve_groups = FALSE; + msg.use_ignore_ticket = FALSE; + msg.use_noninteractive = FALSE; + + msg.debug_level=0; + + msg.runas_user_size = 0; + msg.runas_group_size = 0; + msg.prompt_size = 0; + msg.network_addrs_size = 0; + msg.command_size=0; + + msg.user_env_size = 0; + msg.cli_pid = 0; +} + +/* + * Plugin policy open function. This is called at opening the + * plugin by sudo utility. + * + */ +static int policy_open(unsigned int version, + sudo_conv_t conversation, + sudo_printf_t sudo_printf, + char * const settings[], + char * const user_info[], + char * const user_env[]) +{ + char * const *ui; + struct passwd *pw; + const char *runas_user = NULL; + struct group *gr; + const char *runas_group = NULL; + + + if (sudo_conv == NULL) sudo_conv = conversation; + if (sudo_log == NULL) sudo_log = sudo_printf; + + /* Check the version of sudo plugin api */ + if (SUDO_API_VERSION_GET_MAJOR(version) != SUDO_API_VERSION_MAJOR) { + sudo_log(SUDO_CONV_ERROR_MSG, + "The sss sudo plugin requires API version %d.x\n", + SUDO_API_VERSION_MAJOR); + return ERROR; + } + + init_size_of_msg_contents(); + + + for (ui = settings; *ui != NULL; ui++) { + + /* get the debug level */ + if (strncmp(*ui, "debug_level=", sizeof("debug_level=") - 1) == 0) { + debug_level = atoi(*ui + sizeof("debug_level=") - 1); + msg.debug_level = debug_level; + } + + /* + *check if the user specified the -E flag, indicating that + *the user wishes to preserve the environment. + * + */ + + else if (strncmp(*ui, "preserve_environment=", sizeof("preserve_environment=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("preserve_environment=") - 1, "true") == 0) + msg.use_preserve_environment = TRUE; + } + + /* + * check if the user specified the -H flag. If true, set the + * HOME environment variable to the target user's home directory. + */ + + else if (strncmp(*ui, "set_home=", sizeof("set_home=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("set_home=") - 1, "true") == 0) + msg.use_set_home = TRUE; + } + + /* + * check if the user specified the -s flag, indicating that the + * user wishes to run a shell. + */ + + else if (strncmp(*ui, "run_shell=", sizeof("run_shell=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("run_shell=") - 1, "true") == 0) + msg.use_run_shell = TRUE; + } + + /* + * Check if the user specified the -i flag, indicating that the + * user wishes to run a login shell. + */ + + else if (strncmp(*ui, "login_shell=", sizeof("login_shell=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("login_shell=") - 1, "true") == 0) + msg.use_login_shell = TRUE; + } + + /* + * check to see whether user specified the -k flag along with a + * command, indicating that the user wishes to ignore any cached + * authentication credentials. + */ + + else if (strncmp(*ui, "ignore_ticket=", sizeof("ignore_ticket=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("ignore_ticket=") - 1, "true") == 0) + msg.use_ignore_ticket = TRUE; + } + + /* + * The prompt to use when requesting a password, if specified + * via the -p flag. + */ + + else if (strncmp(*ui, "prompt=", sizeof("prompt=") - 1) == 0) { + msg.prompt = strdup(*ui + sizeof("prompt=") - 1); + msg.prompt_size = (msg.prompt != NULL)? strlen(msg.prompt)+1 : 0; + } + + /* Find the user to be run as */ + + else if (strncmp(*ui, "runas_user=", sizeof("runas_user=") - 1) == 0) { + msg.runas_user = strdup(*ui + sizeof("runas_user=") - 1); + runas_user = msg.runas_user; + msg.runas_user_size = (msg.runas_user != NULL)? strlen(msg.runas_user)+1 : 0; + } + + /* Find the group to be run as */ + + else if (strncmp(*ui, "runas_group=", sizeof("runas_group=") - 1) == 0) { + msg.runas_group = strdup(*ui + sizeof("runas_group=") - 1); + runas_group = msg.runas_group; + msg.runas_group_size = (msg.runas_group != NULL)? strlen(msg.runas_group)+1 : 0; + } + + /* + * To get thhe command name that sudo was run as, typically + * "sudo" or "sudoedit". + */ + +#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) + + else if (strncmp(*ui, "progname=", sizeof("progname=") - 1) == 0) { + setprogname(*ui + sizeof("progname=") - 1); + } +#endif + + /* Check to see if sudo was called as sudoedit or with -e flag. */ + + else if (strncmp(*ui, "sudoedit=", sizeof("sudoedit=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("sudoedit=") - 1, "true") == 0) + use_sudoedit = TRUE; + msg.use_sudoedit = use_sudoedit; + } + + /* This plugin doesn't support running sudo with no arguments. */ + + else if (strncmp(*ui, "implied_shell=", sizeof("implied_shell=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("implied_shell=") - 1, "true") == 0) + return -2; + /* usage error */ + } + + /* + *check to see whether user specified the -P flag, indicating + *that the user wishes to preserve the group vector instead of + *setting it based on the runas user. + */ + + else if (strncmp(*ui, "preserve_groups=", sizeof("preserve_groups=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("preserve_groups=") - 1, "true") == 0) + msg.use_preserve_groups = TRUE; + } + + /* + * check to see whether user specified the -n flag, indicating that + * sudo should operate in non-interactive mode. The plugin may reject + * a command run in non-interactive mode if user interaction is required. + */ + + else if (strncmp(*ui, "noninteractive=", sizeof("noninteractive=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("noninteractive=") - 1, "true") == 0) + msg.use_noninteractive = TRUE; + } + + /* to get network_addrs */ + + else if (strncmp(*ui, "network_addrs=", sizeof("network_addrs=") - 1) == 0) { + msg.network_addrs = strdup(*ui + sizeof("network_addrs=") - 1); + msg.network_addrs_size = (msg.network_addrs != NULL)? strlen(msg.network_addrs)+1 : 0; + } + + /* settings are over */ + } + + + /* Build the user info */ + + for (ui = user_info; *ui != NULL; ui++) { + + /* get user name */ + + if (strncmp(*ui, "user=", sizeof("user=") - 1) == 0) { + user_information.username = strdup(*ui + sizeof("user=") - 1); + } + + /* get user id */ + else if (strncmp(*ui, "uid=", sizeof("uid=") - 1) == 0) { + msg.userid = atoi(*ui + sizeof("uid=") - 1); + } + + + /* get cwd */ + else if (strncmp(*ui, "cwd=", sizeof("cwd=") - 1) == 0) { + msg.cwd = strdup(*ui + sizeof("cwd=") - 1); + msg.cwd_size = (msg.cwd != NULL)? strlen(msg.cwd)+1 : 0; + } + + /* get tty */ + else if (strncmp(*ui, "tty=", sizeof("tty=") - 1) == 0) { + msg.tty = strdup( *ui + sizeof("tty=") - 1); + msg.tty_size = (msg.tty != NULL)? strlen(msg.tty)+1 : 0; + } + + /* get lines - to be removed at final code if no use */ + else if (strncmp(*ui, "lines=", sizeof("lines=") - 1) == 0) { + user_information.lines = atoi(*ui + sizeof("lines=") - 1); + } + + /* get cols - to be removed at final code if no use */ + else if (strncmp(*ui, "cols=", sizeof("cols=") - 1) == 0) { + user_information.cols = atoi(*ui + sizeof("cols=") - 1); + } + } + + + + if (runas_user != NULL) { + if ((pw = getpwnam(runas_user)) == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unknown user %s\n", runas_user); + return 0; + } + runas_uid = pw->pw_uid; + } + if (runas_group != NULL) { + if ((gr = getgrnam(runas_group)) == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unknown group %s\n", runas_group); + return 0; + } + runas_gid = gr->gr_gid; + } + + /* fill Plugin state. */ + plugin_state.envp = (char **)user_env; + msg.user_env = (char **)user_env; + msg.user_env_size = (msg.user_env != NULL)?sizeof msg.user_env :0; + plugin_state.settings = settings; + plugin_state.user_info = user_info; + + return 1; +} + +/* Function to check if the command is available in the PATH */ +static char * find_in_path(char *command, char **envp) +{ + struct stat sb; + char *path; + char *path0; + char **ep; + char *cp = NULL; + char pathbuf[PATH_MAX]; + char *qualified = NULL; + + if (strchr(command, '/') != NULL) + return command; + + path = _PATH_DEFPATH; + for (ep = plugin_state.envp; *ep != NULL; ep++) { + if (strncmp(*ep, "PATH=", 5) == 0) { + path = *ep + 5; + break; + } + } + path = strdup(path); + path0 = path; + + do { + if ((cp = strchr(path, ':'))) + *cp = '\0'; + + snprintf(pathbuf, sizeof(pathbuf), "%s/%s", *path ? path : ".", command); + + if (stat(pathbuf, &sb) == 0) { + if (S_ISREG(sb.st_mode) && (sb.st_mode & 0000111)) { + qualified = pathbuf; + break; + } + } + path = cp + 1; + } while (cp != NULL); + + free(path0); + return ((qualified != NULL) ? strdup(qualified) : NULL); +} + + /* + * Information about the command being run in the form + * of "name=value" strings. These values are used by + * sudo to set the execution environment when running a + * command. The plugin is responsible for creating and + * populating the vector, which must be terminated with a NULL pointer. + * + */ +static char ** build_command_info(char *command) +{ + static char **command_info; + int i = 0; + + /* Setup command info. */ + command_info = calloc(32, sizeof(char *)); + + if (command_info == NULL) + return NULL; + + if (asprintf(&command_info[i++],"%s=%s","command", command) == -1 || + asprintf(&command_info[i++], "runas_euid=%ld", (long)runas_uid) == -1 || + asprintf(&command_info[i++], "runas_uid=%ld", (long)runas_uid) == -1) { + return NULL; + } + + if (runas_gid != -1) { + if (asprintf(&command_info[i++], "runas_gid=%ld", (long)runas_gid) == -1 || + asprintf(&command_info[i++], "runas_egid=%ld", (long)runas_gid) == -1) { + return NULL; + } + } + + if (use_sudoedit) { + command_info[i] = strdup("sudoedit=true"); + if (command_info[i++] == NULL){ + return NULL; + } + } + +#ifdef USE_TIMEOUT + command_info[i++] = "timeout=30"; +#endif + + return command_info; +} + + + /* finds a valid editor for sudo edit or "sudo vi" */ +static char * find_editor(int nfiles, char * const files[], char **argv_out[]) +{ + char *cp; + char **ep; + char **nargv; + char *editor; + char *editor_path; + int ac; + int i; + int nargc; + int wasblank; + + /* Lookup EDITOR in user's environment. */ + editor = _PATH_VI; + for (ep = plugin_state.envp; *ep != NULL; ep++) { + if (strncmp(*ep, "EDITOR=", 7) == 0) { + editor = *ep + 7; + break; + } + } + + editor = strdup(editor); + if (editor == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unable to allocate memory\n"); + return NULL; + } + + /* + * Split editor into an argument vector; editor is reused (do not free). + * The EDITOR environment variables may contain command + * line args so look for those and alloc space for them too. + */ + nargc = 1; + for (wasblank = 0, cp = editor; *cp != '\0'; cp++) { + + if (isblank((unsigned char) *cp)) { + wasblank = 1; + } + else if (wasblank) { + wasblank = 0; + nargc++; + } + } + + /* If we can't find the editor in the user's PATH, give up. */ + cp = strtok(editor, " \t"); + if (cp == NULL || + (editor_path = find_in_path(editor, plugin_state.envp)) == NULL) { + return NULL; + } + + nargv = (char **) malloc((nargc + 1 + nfiles + 1) * sizeof(char *)); + if (nargv == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unable to allocate memory\n"); + return NULL; + } + + for (ac = 0; cp != NULL && ac < nargc; ac++) { + nargv[ac] = cp; + cp = strtok(NULL, " \t"); + } + nargv[ac++] = "--"; + for (i = 0; i < nfiles; ) + nargv[ac++] = files[i++]; + nargv[ac] = NULL; + + *argv_out = nargv; + return editor_path; +} + + + + + + +int sss_sudo_make_request(struct sss_cli_req_data *rd, + uint8_t **repbuf, size_t *replen, + int *errnop) +{ + +/*Here the msg in the rd structure is passed to SSSD with the help of libdbus. + +This isn't coded yet. But I hope the libdbus part can be sompleted today itself*/ + +/* No need to review this function. It is to be cahanged */ + + + const char * param ="hai"; + + + DBusMessage* dbus_msg; + DBusMessageIter args; + DBusConnection* conn; + DBusError err; + DBusPendingCall* pending; + int ret; + int status; + dbus_uint32_t level; + + printf("Calling remote method wit %s\n", (const char *)rd->data); + + /* initialise the errors */ + dbus_error_init(&err); + + /* connect to the system bus and check for errors */ + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err); + if (dbus_error_is_set(&err)) { + fprintf(stderr, "Connection Error (%s)\n", err.message); + dbus_error_free(&err); + } + if (NULL == conn) { + return SSS_SUDO_SYSTEM_ERR; + } + + /* request our name on the bus */ + ret = dbus_bus_request_name(conn, "org.sssd.sudo.request", + DBUS_NAME_FLAG_REPLACE_EXISTING ,&err); + if (dbus_error_is_set(&err)) { + fprintf(stderr, "Name Error (%s)\n", err.message); + dbus_error_free(&err); + } + if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { + return SSS_SUDO_SYSTEM_ERR; + } + + /* create a new method call and check for errors */ + dbus_msg = dbus_message_new_method_call( "org.sssd.sudo.request", /* target */ + "/test/method/Object", /* object */ + "test.method.Type", /* interface */ + "Method"); /* method name */ + if (NULL == dbus_msg) { + fprintf(stderr, "Message Null\n"); + return SSS_SUDO_SYSTEM_ERR; + } + + /* append arguments */ + dbus_message_iter_init_append(dbus_msg, &args); + if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, ¶m)) { + fprintf(stderr, "Out Of Memory!\n"); + exit(1); + } + + /* send message and get a handle for a reply */ + if (!dbus_connection_send_with_reply (conn,dbus_msg, &pending, -1)) { + fprintf(stderr, "Out Of Memory!\n"); + exit(1); + } + if (NULL == pending) { + fprintf(stderr, "Pending Call Null\n"); + exit(1); + } + dbus_connection_flush(conn); + + printf("Request Sent\n"); + + /* free message */ + dbus_message_unref(dbus_msg); + + /* block until we recieve a reply */ + dbus_pending_call_block(pending); + + /* get the reply message */ + dbus_msg = dbus_pending_call_steal_reply(pending); + if (NULL == dbus_msg) { + fprintf(stderr, "Reply Null\n"); + exit(1); + } + /* free the pending message handle */ + dbus_pending_call_unref(pending); + + /* read the parameters */ + if (!dbus_message_iter_init(dbus_msg, &args)) + fprintf(stderr, "Message has no arguments!\n"); + else if (DBUS_TYPE_BOOLEAN != dbus_message_iter_get_arg_type(&args)) + fprintf(stderr, "Argument is not boolean!\n"); + else + dbus_message_iter_get_basic(&args, &status); + + if (!dbus_message_iter_next(&args)) + fprintf(stderr, "Message has too few arguments!\n"); + else if (DBUS_TYPE_UINT32 != dbus_message_iter_get_arg_type(&args)) + fprintf(stderr, "Argument is not int!\n"); + else + dbus_message_iter_get_basic(&args, &level); + + printf("Got Reply: %d, %d\n", status, level); + + // free reply and close connection + dbus_message_unref(dbus_msg); + //dbus_connection_close(conn); + + + + + + + + + + + +return SSS_STATUS_SUCCESS; + +} + + + +static size_t add_string_item(enum sudo_item_type type, const char *str, + const size_t size, uint8_t *buf) { + size_t rp=0; + uint32_t c; + + if (str == NULL || *str == '\0') return 0; + + c = type; + memcpy(&buf[rp], &c, sizeof(uint32_t)); + rp += sizeof(uint32_t); + + c = size; + memcpy(&buf[rp], &c, sizeof(uint32_t)); + rp += sizeof(uint32_t); + + memcpy(&buf[rp], str, size); + rp += size; + + return rp; +} + + +static size_t add_uint32_t_item(enum sudo_item_type type, const uint32_t val, + uint8_t *buf) { + size_t rp=0; + uint32_t c; + + c = type; + memcpy(&buf[rp], &c, sizeof(uint32_t)); + rp += sizeof(uint32_t); + + c = sizeof(uint32_t); + memcpy(&buf[rp], &c, sizeof(uint32_t)); + rp += sizeof(uint32_t); + + c = val; + memcpy(&buf[rp], &c, sizeof(uint32_t)); + rp += sizeof(uint32_t); + + return rp; +} + + + +static int pack_message_sudo_v1( size_t *size, uint8_t **buffer) { + + int len; + uint8_t *buf; + int rp; + uint32_t terminator = SSS_END_OF_SUDO_REQUEST; + + len = sizeof(uint32_t) + 3*sizeof(uint32_t) +sizeof(uint32_t); // msg.user_id ; + + len += *msg.cwd != '\0' ?2*sizeof(uint32_t) + msg.cwd_size : 0; + + len += *msg.tty != '\0' ?2*sizeof(uint32_t) + msg.tty_size : 0; + + len += msg.runas_user != NULL ?2*sizeof(uint32_t) + msg.runas_user_size : 0; + + len += msg.runas_group != NULL ?2*sizeof(uint32_t) + msg.runas_group_size : 0; + + len += msg.prompt != NULL ?2*sizeof(uint32_t) + msg.prompt_size : 0; + + len += msg.network_addrs != NULL ?2*sizeof(uint32_t) + msg.network_addrs_size : 0; + + len += 3*sizeof(uint32_t); //msg.use_sudoedit + + len += 3*sizeof(uint32_t); // msg.use_set_home ; + + len += 3*sizeof(uint32_t); //msg.use_preserve_environment ; + + len += 3*sizeof(uint32_t); // msg.use_implied_shell ; + + len += 3*sizeof(uint32_t);// msg.use_login_shell ; + + len += 3*sizeof(uint32_t);// msg.use_run_shell ; + + len += 3*sizeof(uint32_t); // msg.use_preserve_groups ; + + len += 3*sizeof(uint32_t); // msg.use_ignore_ticket ; + + len += 3*sizeof(uint32_t);; // msg.use_noninteractive ; + + len += 3*sizeof(uint32_t); // msg.debug_level ; + + len += *msg.command != '\0' ? + 2*sizeof(uint32_t) + msg.command_size : 0; + + len += 3*sizeof(uint32_t) ; //msg.user_env : 0; + + len += 3*sizeof(uint32_t); /* cli_pid */ + + buf = malloc(len); + if (buf == NULL) { + // D(("malloc failed.")); + return SSS_SUDO_BUF_ERR; + } + + rp = 0; + ((uint32_t *)(&buf[rp]))[0] = SSS_START_OF_SUDO_REQUEST; + rp += sizeof(uint32_t); + + + rp += add_uint32_t_item(SSS_SUDO_ITEM_UID, (uint32_t) msg.userid, + &buf[rp]); + + + rp += add_string_item(SSS_SUDO_ITEM_CWD, msg.cwd, + msg.cwd_size, &buf[rp]); + + rp += add_string_item(SSS_SUDO_ITEM_TTY, msg.tty, + msg.tty_size, &buf[rp]); + + rp += add_string_item(SSS_SUDO_ITEM_RUSER, msg.runas_user, + msg.runas_user_size, &buf[rp]); + + rp += add_string_item(SSS_SUDO_ITEM_RGROUP, msg.runas_group, + msg.runas_group_size, &buf[rp]); + + rp += add_string_item(SSS_SUDO_ITEM_PROMPT, msg.prompt, + msg.prompt_size, &buf[rp]); + + rp += add_string_item(SSS_SUDO_ITEM_NETADDR, msg.network_addrs, + msg.network_addrs_size, &buf[rp]); + + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_SUDOEDIT, (uint32_t) msg.use_sudoedit, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_SETHOME, (uint32_t) msg.use_set_home, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_PRESERV_ENV, (uint32_t) msg.use_preserve_environment, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_IMPLIED_SHELL, (uint32_t) msg.use_implied_shell, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_LOGIN_SHELL, (uint32_t) msg.use_login_shell, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_RUN_SHELL, (uint32_t) msg.use_run_shell, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_PRE_GROUPS, (uint32_t) msg.use_preserve_groups, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_IGNORE_TICKET, (uint32_t) msg.use_ignore_ticket, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USE_NON_INTERACTIVE, (uint32_t) msg.use_noninteractive, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_DEBUG_LEVEL, (uint32_t) msg.debug_level, + &buf[rp]); + + + rp += add_string_item(SSS_SUDO_ITEM_COMMAND, msg.command, + msg.command_size, &buf[rp]); + + + rp += add_uint32_t_item(SSS_SUDO_ITEM_USER_ENV, (uint32_t) msg.user_env, + &buf[rp]); + + rp += add_uint32_t_item(SSS_SUDO_ITEM_CLI_PID, (uint32_t) getpid(), + &buf[rp]); + + + + memcpy(&buf[rp], &terminator, sizeof(uint32_t)); + rp += sizeof(uint32_t); + + if (rp != len) { + //D(("error during packet creation.")); + free(buf); + return SSS_SUDO_BUF_ERR; + } + + *size = len; + *buffer = buf; + + return 0; +} + + + + + +static int send_and_receive() +{ + int ret; + int errnop; + struct sss_cli_req_data rd; + uint8_t *buf = NULL; + uint8_t *repbuf = NULL; + size_t replen; + int _status = SSS_SUDO_SYSTEM_ERR; + + print_sudo_items(); + + ret = pack_message_sudo_v1(&rd.len, &buf); + if (ret == SSS_SUDO_BUF_ERR) { + // D(("pack_message failed.")); + _status = SSS_SUDO_SYSTEM_ERR; + goto done; + } + rd.data = buf; + + errnop = 0; + ret = sss_sudo_make_request( &rd, &repbuf, &replen, &errnop); + + if (ret != SSS_SUDO_SUCCESS) { + if (errnop != 0) { + fprintf( stderr, "Request to sssd failed. %d", errnop); + } + _status = SSS_SUDO_SYSTEM_ERR; + goto done; + } + +/* FIXME: add an end signature */ + if (replen < (2*sizeof(int32_t))) { + //D(("response not in expected format.")); + _status = SSS_SUDO_SYSTEM_ERR; + goto done; + } + + _status = ((int32_t *)repbuf)[0]; + //ret = eval_response(replen, repbuf); + if (ret != SSS_SUDO_SUCCESS) { + // D(("eval_response failed.")); + _status = ret; + goto done; + } + + if (_status != SSS_SUDO_SUCCESS) { + //D( "received for user %s: %d (%d)", user_information.username, _status, _status); + } + + +done: + if (buf != NULL ) { + free(buf); + } + free(repbuf); + +_status = SSS_STATUS_SUCCESS; + +if (_status == SSS_STATUS_SUCCESS) + return _status; +else + return SSS_STATUS_UNAVAIL; +} + + + +/* + * Plugin policy check function. + * The check_policy function is called by sudo to determine + * whether the user is allowed to run the specified commands. + */ +static int policy_check(int argc, char * const argv[], + char *env_add[], char **command_info_out[], + char **argv_out[], char **user_env_out[]) +{ + char *command; + pam_handle_t *pamh; + char *pam_user; + char *pam_action; + int pam_ret; + + if (!argc || argv[0] == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "no command specified\n"); + return FALSE; + } + + + command = find_in_path(argv[0], plugin_state.envp); + if (command == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "%s: command not found\n", argv[0]); + return FALSE; + } + + /* If "sudo vi" is run, auto-convert to sudoedit. */ + if (strcmp(command, _PATH_VI) == 0) + use_sudoedit = TRUE; + + if (use_sudoedit) { + /* Rebuild argv using editor */ + command = find_editor(argc - 1, argv + 1, argv_out); + if (command == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unable to find valid editor\n"); + return ERROR; + } + use_sudoedit = TRUE; + } else { + /* No changes needd to argv */ + *argv_out = (char **)argv; + } + + /* No changes to envp */ + *user_env_out = plugin_state.envp; + + /* Space for authentication */ + + pam_action = strdup("auth"); + pam_user = user_information.username; + + sudo_log(SUDO_CONV_INFO_MSG, "\nCalling PAM with action: %s\nuser: %s\n", pam_action,pam_user); + pam_ret = pam_start(SSS_SUDO_PAM_SERVICE, pam_user, &conv, &pamh); + + if (pam_ret != PAM_SUCCESS) { + fprintf(stderr, "pam_start failed: %s\n", pam_strerror(pamh, pam_ret)); + return 0; + } + + pam_ret = pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK); + switch(pam_ret) { + case PAM_ABORT: + fprintf(stderr, "pam_authenticate - aborted: %s\n", pam_strerror(pamh, pam_ret)); + pam_end(pamh, pam_ret); + return 0; + + case PAM_AUTH_ERR: + fprintf(stderr, "pam_authenticate - error: %s\n", pam_strerror(pamh, pam_ret)); + pam_end(pamh, pam_ret); + return 0; + + case PAM_SUCCESS: + fprintf(stdout, "pam_authenticate - success: %s\n", pam_strerror(pamh, pam_ret)); + break; + + case PAM_CRED_INSUFFICIENT: + fprintf(stderr, "pam_authenticate - crendential not sufficient: %s\n", pam_strerror(pamh, pam_ret)); + pam_end(pamh, pam_ret); + return 0; + + case PAM_AUTHINFO_UNAVAIL: + fprintf(stderr, "pam_authenticate - authentication information not available: %s\n", pam_strerror(pamh, pam_ret)); + pam_end(pamh, pam_ret); + return 0; + + case PAM_USER_UNKNOWN: + fprintf(stderr, "pam_authenticate - check the user specified : %s\n", pam_strerror(pamh, pam_ret)); + pam_end(pamh, pam_ret); + return 0; + + case PAM_MAXTRIES: + fprintf(stderr, "pam_authenticate - maximum tries over : %s\n", pam_strerror(pamh, pam_ret)); + pam_end(pamh, pam_ret); + return 0; + + default: + fprintf(stderr, "pam_authenticate - unknown error : %s\n", pam_strerror(pamh, pam_ret)); + pam_end(pamh, pam_ret); + return 0; + + } + + /* pam is success :) */ + pam_end(pamh, pam_ret); + + msg.command = command; + msg.command_size = (msg.command)? sizeof msg.command:0; + + if(pam_ret==PAM_SUCCESS) { + + pam_ret = send_and_receive(); + } + + /* Setup command info. */ + *command_info_out = build_command_info(command); + if (*command_info_out == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "out of memory\n"); + return ERROR; + } + if(pam_ret==SSS_STATUS_SUCCESS) + return TRUE; + + return FALSE; +} + +static int policy_list(int argc, char * const argv[], int verbose, const char *list_user) +{ + /* + * List user's capabilities. + */ + sudo_log(SUDO_CONV_INFO_MSG, "Validated users may run any command. Currently validation isn't coded. :/\n"); + return TRUE; +} + + + +static int policy_version(int verbose) +{ + sudo_log(SUDO_CONV_INFO_MSG, "%sv\nSudo Plugin API version %dv\nSSSD sudo plugin version %s\n", SUDO_PACKAGE_STRING,SUDO_API_VERSION,SSS_SUDO_PLUGIN_VERSION); + return TRUE; +} + + +static void policy_close(int exit_status, int error) +{ + /* + * The close function is called when the command being run by sudo finishes. + */ + if (error) { + sudo_log(SUDO_CONV_ERROR_MSG, "\nCommand error: %s\n", strerror(error)); + } else { + if (WIFEXITED(exit_status)) { + sudo_log(SUDO_CONV_INFO_MSG, "\nCommand exited with status %d\n", + WEXITSTATUS(exit_status)); + } else if (WIFSIGNALED(exit_status)) { + sudo_log(SUDO_CONV_INFO_MSG, "\nCommand killed by signal %d\n", + WTERMSIG(exit_status)); + } + } +} + + +/* IO_PLUGIN is not needed */ + + +struct policy_plugin sss_sudo_policy = { + SUDO_POLICY_PLUGIN, + SUDO_API_VERSION, + policy_open, + policy_close, + policy_version, + policy_check, + policy_list, + NULL, /* validate */ + NULL /* invalidate */ +}; + + + |