version 1.1.1.2, 2012/05/29 12:26:49
|
version 1.1.1.3, 2012/10/09 09:29:52
|
Line 55
|
Line 55
|
#endif |
#endif |
|
|
/* |
/* |
* Load the plugins listed in sudo.conf. | * Load the plugin specified by "info". |
*/ |
*/ |
bool | static bool |
sudo_load_plugins(struct plugin_container *policy_plugin, | sudo_load_plugin(struct plugin_container *policy_plugin, |
struct plugin_container_list *io_plugins) | struct plugin_container_list *io_plugins, struct plugin_info *info) |
{ |
{ |
struct plugin_info_list *plugins; |
|
struct generic_plugin *plugin; |
|
struct plugin_container *container; |
struct plugin_container *container; |
struct plugin_info *info; | struct generic_plugin *plugin; |
struct stat sb; |
struct stat sb; |
void *handle; |
void *handle; |
char path[PATH_MAX]; |
char path[PATH_MAX]; |
bool rval = false; |
bool rval = false; |
debug_decl(sudo_load_plugins, SUDO_DEBUG_PLUGIN) | debug_decl(sudo_load_plugin, SUDO_DEBUG_PLUGIN) |
|
|
/* Walk plugin list. */ | if (info->path[0] == '/') { |
plugins = sudo_conf_plugins(); | if (strlcpy(path, info->path, sizeof(path)) >= sizeof(path)) { |
tq_foreach_fwd(plugins, info) { | warningx(_("%s: %s"), info->path, strerror(ENAMETOOLONG)); |
if (info->path[0] == '/') { | |
if (strlcpy(path, info->path, sizeof(path)) >= sizeof(path)) { | |
warningx(_("%s: %s"), info->path, strerror(ENAMETOOLONG)); | |
goto done; | |
} | |
} else { | |
if (snprintf(path, sizeof(path), "%s%s", _PATH_SUDO_PLUGIN_DIR, | |
info->path) >= sizeof(path)) { | |
warningx(_("%s%s: %s"), _PATH_SUDO_PLUGIN_DIR, info->path, | |
strerror(ENAMETOOLONG)); | |
goto done; | |
} | |
} | |
if (stat(path, &sb) != 0) { | |
warning("%s", path); | |
goto done; |
goto done; |
} |
} |
if (sb.st_uid != ROOT_UID) { | } else { |
warningx(_("%s must be owned by uid %d"), path, ROOT_UID); | if (snprintf(path, sizeof(path), "%s%s", _PATH_SUDO_PLUGIN_DIR, |
| info->path) >= sizeof(path)) { |
| warningx(_("%s%s: %s"), _PATH_SUDO_PLUGIN_DIR, info->path, |
| strerror(ENAMETOOLONG)); |
goto done; |
goto done; |
} |
} |
if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { | } |
warningx(_("%s must be only be writable by owner"), path); | if (stat(path, &sb) != 0) { |
| warning("%s", path); |
| goto done; |
| } |
| if (sb.st_uid != ROOT_UID) { |
| warningx(_("%s must be owned by uid %d"), path, ROOT_UID); |
| goto done; |
| } |
| if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { |
| warningx(_("%s must be only be writable by owner"), path); |
| goto done; |
| } |
| |
| /* Open plugin and map in symbol */ |
| handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL); |
| if (!handle) { |
| warningx(_("unable to dlopen %s: %s"), path, dlerror()); |
| goto done; |
| } |
| plugin = dlsym(handle, info->symbol_name); |
| if (!plugin) { |
| warningx(_("%s: unable to find symbol %s"), path, |
| info->symbol_name); |
| goto done; |
| } |
| |
| if (plugin->type != SUDO_POLICY_PLUGIN && plugin->type != SUDO_IO_PLUGIN) { |
| warningx(_("%s: unknown policy type %d"), path, plugin->type); |
| goto done; |
| } |
| if (SUDO_API_VERSION_GET_MAJOR(plugin->version) != SUDO_API_VERSION_MAJOR) { |
| warningx(_("%s: incompatible policy major version %d, expected %d"), |
| path, SUDO_API_VERSION_GET_MAJOR(plugin->version), |
| SUDO_API_VERSION_MAJOR); |
| goto done; |
| } |
| if (plugin->type == SUDO_POLICY_PLUGIN) { |
| if (policy_plugin->handle) { |
| warningx(_("%s: only a single policy plugin may be loaded"), |
| _PATH_SUDO_CONF); |
goto done; |
goto done; |
} |
} |
|
policy_plugin->handle = handle; |
|
policy_plugin->name = info->symbol_name; |
|
policy_plugin->options = info->options; |
|
policy_plugin->u.generic = plugin; |
|
} else if (plugin->type == SUDO_IO_PLUGIN) { |
|
container = ecalloc(1, sizeof(*container)); |
|
container->prev = container; |
|
/* container->next = NULL; */ |
|
container->handle = handle; |
|
container->name = info->symbol_name; |
|
container->options = info->options; |
|
container->u.generic = plugin; |
|
tq_append(io_plugins, container); |
|
} |
|
|
/* Open plugin and map in symbol */ | rval = true; |
handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL); | done: |
if (!handle) { | debug_return_bool(rval); |
warningx(_("unable to dlopen %s: %s"), path, dlerror()); | } |
| |
| /* |
| * Load the plugins listed in sudo.conf. |
| */ |
| bool |
| sudo_load_plugins(struct plugin_container *policy_plugin, |
| struct plugin_container_list *io_plugins) |
| { |
| struct plugin_container *container; |
| struct plugin_info_list *plugins; |
| struct plugin_info *info; |
| bool rval = false; |
| debug_decl(sudo_load_plugins, SUDO_DEBUG_PLUGIN) |
| |
| /* Walk the plugin list from sudo.conf, if any. */ |
| plugins = sudo_conf_plugins(); |
| tq_foreach_fwd(plugins, info) { |
| rval = sudo_load_plugin(policy_plugin, io_plugins, info); |
| if (!rval) |
goto done; |
goto done; |
} | } |
plugin = dlsym(handle, info->symbol_name); | |
if (!plugin) { | |
warningx(_("%s: unable to find symbol %s"), path, | |
info->symbol_name); | |
goto done; | |
} | |
|
|
if (plugin->type != SUDO_POLICY_PLUGIN && plugin->type != SUDO_IO_PLUGIN) { | /* |
warningx(_("%s: unknown policy type %d"), path, plugin->type); | * If no policy plugin, fall back to the default (sudoers). |
| * If there is also no I/O log plugin, sudoers for that too. |
| */ |
| if (policy_plugin->handle == NULL) { |
| /* Default policy plugin */ |
| info = ecalloc(1, sizeof(*info)); |
| info->symbol_name = "sudoers_policy"; |
| info->path = SUDOERS_PLUGIN; |
| /* info->options = NULL; */ |
| info->prev = info; |
| /* info->next = NULL; */ |
| rval = sudo_load_plugin(policy_plugin, io_plugins, info); |
| efree(info); |
| if (!rval) |
goto done; |
goto done; |
} | |
if (SUDO_API_VERSION_GET_MAJOR(plugin->version) != SUDO_API_VERSION_MAJOR) { | /* Default I/O plugin */ |
warningx(_("%s: incompatible policy major version %d, expected %d"), | if (tq_empty(io_plugins)) { |
path, SUDO_API_VERSION_GET_MAJOR(plugin->version), | info = ecalloc(1, sizeof(*info)); |
SUDO_API_VERSION_MAJOR); | info->symbol_name = "sudoers_io"; |
goto done; | info->path = SUDOERS_PLUGIN; |
} | /* info->options = NULL; */ |
if (plugin->type == SUDO_POLICY_PLUGIN) { | info->prev = info; |
if (policy_plugin->handle) { | /* info->next = NULL; */ |
warningx(_("%s: only a single policy plugin may be loaded"), | rval = sudo_load_plugin(policy_plugin, io_plugins, info); |
_PATH_SUDO_CONF); | efree(info); |
| if (!rval) |
goto done; |
goto done; |
} |
|
policy_plugin->handle = handle; |
|
policy_plugin->name = info->symbol_name; |
|
policy_plugin->options = info->options; |
|
policy_plugin->u.generic = plugin; |
|
} else if (plugin->type == SUDO_IO_PLUGIN) { |
|
container = ecalloc(1, sizeof(*container)); |
|
container->prev = container; |
|
/* container->next = NULL; */ |
|
container->handle = handle; |
|
container->name = info->symbol_name; |
|
container->options = info->options; |
|
container->u.generic = plugin; |
|
tq_append(io_plugins, container); |
|
} |
} |
} |
} |
if (policy_plugin->handle == NULL) { |
|
warningx(_("%s: at least one policy plugin must be specified"), |
|
_PATH_SUDO_CONF); |
|
goto done; |
|
} |
|
if (policy_plugin->u.policy->check_policy == NULL) { |
if (policy_plugin->u.policy->check_policy == NULL) { |
warningx(_("policy plugin %s does not include a check_policy method"), |
warningx(_("policy plugin %s does not include a check_policy method"), |
policy_plugin->name); |
policy_plugin->name); |
|
rval = false; |
goto done; |
goto done; |
} |
} |
|
|
Line 159 sudo_load_plugins(struct plugin_container *policy_plug
|
Line 207 sudo_load_plugins(struct plugin_container *policy_plug
|
if (policy_plugin->u.policy->version >= SUDO_API_MKVERSION(1, 2)) { |
if (policy_plugin->u.policy->version >= SUDO_API_MKVERSION(1, 2)) { |
if (policy_plugin->u.policy->register_hooks != NULL) |
if (policy_plugin->u.policy->register_hooks != NULL) |
policy_plugin->u.policy->register_hooks(SUDO_HOOK_VERSION, register_hook); |
policy_plugin->u.policy->register_hooks(SUDO_HOOK_VERSION, register_hook); |
tq_foreach_fwd(io_plugins, container) { | } |
| tq_foreach_fwd(io_plugins, container) { |
| if (container->u.io->version >= SUDO_API_MKVERSION(1, 2)) { |
if (container->u.io->register_hooks != NULL) |
if (container->u.io->register_hooks != NULL) |
container->u.io->register_hooks(SUDO_HOOK_VERSION, register_hook); |
container->u.io->register_hooks(SUDO_HOOK_VERSION, register_hook); |
} |
} |
} |
} |
|
|
rval = true; |
|
|
|
done: |
done: |
debug_return_bool(rval); |
debug_return_bool(rval); |