summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArun Scaria <arunscaria91@gmail.com>2011-06-22 13:48:18 +0530
committerArun Scaria <arunscaria91@gmail.com>2011-06-22 13:48:18 +0530
commit9be6ed2d662d57e7d595714aa85126a84727e49b (patch)
tree98c223d1cd1270c568e53338c114342f38184f76
parentfe8426ea00e7cf6194f0fab9606b3937c4ea3344 (diff)
downloadsssd_unused-9be6ed2d662d57e7d595714aa85126a84727e49b.tar.gz
sssd_unused-9be6ed2d662d57e7d595714aa85126a84727e49b.tar.xz
sssd_unused-9be6ed2d662d57e7d595714aa85126a84727e49b.zip
New Make + new plugin code
-rw-r--r--Makefile.am27
-rw-r--r--src/responder/sudo/sudosrv.c95
-rw-r--r--src/sss_client/sudo_plugin/README52
-rw-r--r--src/sss_client/sudo_plugin/missing.h48
-rw-r--r--src/sss_client/sudo_plugin/sss_sudo_cli.h89
-rw-r--r--src/sss_client/sudo_plugin/sss_sudoplugin.c1265
6 files changed, 1574 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am
index b8423bab..37819e41 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,6 +24,7 @@ dbusintrospectdir = $(datarootdir)/sssd/introspect
localedir = @localedir@
nsslibdir = @nsslibdir@
pamlibdir = @pammoddir@
+libsss_sudoplugindir = $(libexecdir)
dbpath = @dbpath@
pluginpath = @pluginpath@
@@ -63,7 +64,8 @@ sssdlibexec_PROGRAMS = \
sssd_be \
krb5_child \
ldap_child \
- proxy_child
+ proxy_child \
+ sssd_sudo
if HAVE_CHECK
non_interactive_check_based_tests = \
@@ -191,7 +193,8 @@ AM_CPPFLAGS = \
-DSSS_NSS_SOCKET_NAME=\"$(pipepath)/nss\" \
-DSSS_PAM_SOCKET_NAME=\"$(pipepath)/pam\" \
-DSSS_PAM_PRIV_SOCKET_NAME=\"$(pipepath)/private/pam\" \
- -DLOCALEDIR=\"$(localedir)\"
+ -DLOCALEDIR=\"$(localedir)\" \
+ -D_GNU_SOURCE
EXTRA_DIST = build/config.rpath
@@ -398,6 +401,13 @@ sssd_pam_LDADD = \
$(SSSD_LIBS) \
libsss_util.la
+sssd_sudo_SOURCES = \
+ src/responder/sudo/sudosrv.c
+sssd_sudo_LDADD = \
+ $(TDB_LIBS) \
+ $(SSSD_LIBS) \
+ libsss_util.la
+
sssd_be_SOURCES = \
src/providers/data_provider_be.c \
src/providers/data_provider_fo.c \
@@ -758,6 +768,19 @@ dist_noinst_DATA += \
src/sss_client/sss_nss.exports \
src/sss_client/sss_pam.exports
+libsss_sudoplugin_LTLIBRARIES = libsss_sudoplugin.la
+libsss_sudoplugin_la_SOURCES = \
+ src/sss_client/sudo_plugin/sss_sudoplugin.c \
+ src/sss_client/sudo_plugin/sss_sudo_cli.h \
+ src/sss_client/sudo_plugin/missing.h
+
+libsss_sudoplugin_la_LDFLAGS = \
+ -module \
+ -lpam \
+ -lpam_misc \
+ `pkg-config --cflags --libs dbus-1`
+
+
####################
# Plugin Libraries #
####################
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, &param)) {
+ 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 */
+};
+
+
+