2 * Copyright (c) 2010 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>
20 #include <sys/param.h>
31 #endif /* STDC_HEADERS */
34 #endif /* HAVE_STRING_H */
37 #endif /* HAVE_STRINGS_H */
40 #endif /* HAVE_UNISTD_H */
41 #if TIME_WITH_SYS_TIME
47 # include "compat/dlfcn.h"
56 # define RTLD_GLOBAL 0
59 #if defined(HAVE_DLOPEN) || defined(HAVE_SHL_LOAD)
61 static void *group_handle;
62 static struct sudoers_group_plugin *group_plugin;
65 * Load the specified plugin and run its init function.
66 * Returns -1 if unable to open the plugin, else it returns
67 * the value from the plugin's init function.
70 group_plugin_load(char *plugin_info)
73 char *args, path[PATH_MAX];
76 debug_decl(group_plugin_load, SUDO_DEBUG_UTIL)
79 * Fill in .so path and split out args (if any).
81 if ((args = strpbrk(plugin_info, " \t")) != NULL) {
82 len = snprintf(path, sizeof(path), "%s%.*s",
83 (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "",
84 (int)(args - plugin_info), plugin_info);
87 len = snprintf(path, sizeof(path), "%s%s",
88 (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", plugin_info);
90 if (len <= 0 || len >= sizeof(path)) {
91 warningx(_("%s%s: %s"),
92 (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", plugin_info,
93 strerror(ENAMETOOLONG));
97 /* Sanity check plugin path. */
98 if (stat(path, &sb) != 0) {
102 if (sb.st_uid != ROOT_UID) {
103 warningx(_("%s must be owned by uid %d"), path, ROOT_UID);
106 if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
107 warningx(_("%s must only be writable by owner"), path);
111 /* Open plugin and map in symbol. */
112 group_handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL);
114 warningx(_("unable to dlopen %s: %s"), path, dlerror());
117 group_plugin = dlsym(group_handle, "group_plugin");
118 if (group_plugin == NULL) {
119 warningx(_("unable to find symbol \"group_plugin\" in %s"), path);
123 if (GROUP_API_VERSION_GET_MAJOR(group_plugin->version) != GROUP_API_VERSION_MAJOR) {
124 warningx(_("%s: incompatible group plugin major version %d, expected %d"),
125 path, GROUP_API_VERSION_GET_MAJOR(group_plugin->version),
126 GROUP_API_VERSION_MAJOR);
131 * Split args into a vector if specified.
135 bool wasblank = true;
138 for (cp = args; *cp != '\0'; cp++) {
139 if (isblank((unsigned char)*cp)) {
141 } else if (wasblank) {
147 argv = emalloc2(ac, sizeof(char *));
149 for ((cp = strtok(args, " \t")); cp; (cp = strtok(NULL, " \t")))
154 rc = (group_plugin->init)(GROUP_API_VERSION, sudo_printf, argv);
160 if (group_handle != NULL) {
161 dlclose(group_handle);
167 debug_return_bool(rc);
171 group_plugin_unload(void)
173 debug_decl(group_plugin_unload, SUDO_DEBUG_UTIL)
175 if (group_plugin != NULL) {
176 (group_plugin->cleanup)();
179 if (group_handle != NULL) {
180 dlclose(group_handle);
187 group_plugin_query(const char *user, const char *group,
188 const struct passwd *pwd)
190 debug_decl(group_plugin_query, SUDO_DEBUG_UTIL)
192 if (group_plugin == NULL)
193 debug_return_bool(false);
194 debug_return_bool((group_plugin->query)(user, group, pwd));
197 #else /* !HAVE_DLOPEN && !HAVE_SHL_LOAD */
200 * No loadable shared object support.
204 group_plugin_load(char *plugin_info)
206 debug_decl(group_plugin_load, SUDO_DEBUG_UTIL)
207 debug_return_bool(false);
211 group_plugin_unload(void)
213 debug_decl(group_plugin_unload, SUDO_DEBUG_UTIL)
218 group_plugin_query(const char *user, const char *group,
219 const struct passwd *pwd)
221 debug_decl(group_plugin_query, SUDO_DEBUG_UTIL)
222 debug_return_bool(false);
225 #endif /* HAVE_DLOPEN || HAVE_SHL_LOAD */