2 * Copyright (c) 2010-2013 Todd C. Miller <Todd.Miller@courtesan.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
30 #endif /* STDC_HEADERS */
33 #endif /* HAVE_STRING_H */
36 #endif /* HAVE_STRINGS_H */
39 #endif /* HAVE_UNISTD_H */
40 #if TIME_WITH_SYS_TIME
46 # include "compat/dlfcn.h"
55 # define RTLD_GLOBAL 0
58 #if defined(HAVE_DLOPEN) || defined(HAVE_SHL_LOAD)
60 static void *group_handle;
61 static struct sudoers_group_plugin *group_plugin;
64 * Load the specified plugin and run its init function.
65 * Returns -1 if unable to open the plugin, else it returns
66 * the value from the plugin's init function.
69 group_plugin_load(char *plugin_info)
72 char *args, path[PATH_MAX];
75 debug_decl(group_plugin_load, SUDO_DEBUG_UTIL)
78 * Fill in .so path and split out args (if any).
80 if ((args = strpbrk(plugin_info, " \t")) != NULL) {
81 len = snprintf(path, sizeof(path), "%s%.*s",
82 (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "",
83 (int)(args - plugin_info), plugin_info);
86 len = snprintf(path, sizeof(path), "%s%s",
87 (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", plugin_info);
89 if (len <= 0 || len >= sizeof(path)) {
92 (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", plugin_info);
96 /* Sanity check plugin path. */
97 if (stat(path, &sb) != 0) {
101 if (sb.st_uid != ROOT_UID) {
102 warningx(_("%s must be owned by uid %d"), path, ROOT_UID);
105 if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
106 warningx(_("%s must only be writable by owner"), path);
110 /* Open plugin and map in symbol. */
111 group_handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL);
113 warningx(_("unable to dlopen %s: %s"), path, dlerror());
116 group_plugin = dlsym(group_handle, "group_plugin");
117 if (group_plugin == NULL) {
118 warningx(_("unable to find symbol \"group_plugin\" in %s"), path);
122 if (GROUP_API_VERSION_GET_MAJOR(group_plugin->version) != GROUP_API_VERSION_MAJOR) {
123 warningx(_("%s: incompatible group plugin major version %d, expected %d"),
124 path, GROUP_API_VERSION_GET_MAJOR(group_plugin->version),
125 GROUP_API_VERSION_MAJOR);
130 * Split args into a vector if specified.
134 bool wasblank = true;
137 for (cp = args; *cp != '\0'; cp++) {
138 if (isblank((unsigned char)*cp)) {
140 } else if (wasblank) {
146 argv = emalloc2(ac, sizeof(char *));
148 for ((cp = strtok(args, " \t")); cp; (cp = strtok(NULL, " \t")))
153 rc = (group_plugin->init)(GROUP_API_VERSION, sudo_printf, argv);
159 if (group_handle != NULL) {
160 dlclose(group_handle);
166 debug_return_bool(rc);
170 group_plugin_unload(void)
172 debug_decl(group_plugin_unload, SUDO_DEBUG_UTIL)
174 if (group_plugin != NULL) {
175 (group_plugin->cleanup)();
178 if (group_handle != NULL) {
179 dlclose(group_handle);
186 group_plugin_query(const char *user, const char *group,
187 const struct passwd *pwd)
189 debug_decl(group_plugin_query, SUDO_DEBUG_UTIL)
191 if (group_plugin == NULL)
192 debug_return_bool(false);
193 debug_return_bool((group_plugin->query)(user, group, pwd));
196 #else /* !HAVE_DLOPEN && !HAVE_SHL_LOAD */
199 * No loadable shared object support.
203 group_plugin_load(char *plugin_info)
205 debug_decl(group_plugin_load, SUDO_DEBUG_UTIL)
206 debug_return_bool(false);
210 group_plugin_unload(void)
212 debug_decl(group_plugin_unload, SUDO_DEBUG_UTIL)
217 group_plugin_query(const char *user, const char *group,
218 const struct passwd *pwd)
220 debug_decl(group_plugin_query, SUDO_DEBUG_UTIL)
221 debug_return_bool(false);
224 #endif /* HAVE_DLOPEN || HAVE_SHL_LOAD */