Annotation of embedaddon/sudo/plugins/sudoers/group_plugin.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
! 3: *
! 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.
! 7: *
! 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.
! 15: */
! 16:
! 17: #include <config.h>
! 18:
! 19: #if defined(HAVE_DLOPEN) || defined(HAVE_SHL_LOAD)
! 20:
! 21: #include <sys/types.h>
! 22: #include <sys/param.h>
! 23: #include <sys/stat.h>
! 24: #include <sys/time.h>
! 25: #include <stdio.h>
! 26: #ifdef STDC_HEADERS
! 27: # include <stdlib.h>
! 28: # include <stddef.h>
! 29: #else
! 30: # ifdef HAVE_STDLIB_H
! 31: # include <stdlib.h>
! 32: # endif
! 33: #endif /* STDC_HEADERS */
! 34: #ifdef HAVE_STRING_H
! 35: # include <string.h>
! 36: #endif /* HAVE_STRING_H */
! 37: #ifdef HAVE_STRINGS_H
! 38: # include <strings.h>
! 39: #endif /* HAVE_STRINGS_H */
! 40: #ifdef HAVE_UNISTD_H
! 41: # include <unistd.h>
! 42: #endif /* HAVE_UNISTD_H */
! 43: #if TIME_WITH_SYS_TIME
! 44: # include <time.h>
! 45: #endif
! 46: #ifdef HAVE_DLOPEN
! 47: # include <dlfcn.h>
! 48: #else
! 49: # include "compat/dlfcn.h"
! 50: #endif
! 51: #include <ctype.h>
! 52: #include <errno.h>
! 53: #include <pwd.h>
! 54:
! 55: #include "sudoers.h"
! 56:
! 57: #ifndef RTLD_GLOBAL
! 58: # define RTLD_GLOBAL 0
! 59: #endif
! 60:
! 61: static void *group_handle;
! 62: static struct sudoers_group_plugin *group_plugin;
! 63:
! 64: /*
! 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.
! 68: */
! 69: int
! 70: group_plugin_load(char *plugin_info)
! 71: {
! 72: struct stat sb;
! 73: char *args, path[PATH_MAX];
! 74: char **argv = NULL;
! 75: int len, rc = -1;
! 76:
! 77: /*
! 78: * Fill in .so path and split out args (if any).
! 79: */
! 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);
! 84: args++;
! 85: } else {
! 86: len = snprintf(path, sizeof(path), "%s%s",
! 87: (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", plugin_info);
! 88: }
! 89: if (len <= 0 || len >= sizeof(path)) {
! 90: warningx(_("%s%s: %s"),
! 91: (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", plugin_info,
! 92: strerror(ENAMETOOLONG));
! 93: goto done;
! 94: }
! 95:
! 96: /* Sanity check plugin path. */
! 97: if (stat(path, &sb) != 0) {
! 98: warning("%s", path);
! 99: goto done;
! 100: }
! 101: if (sb.st_uid != ROOT_UID) {
! 102: warningx(_("%s must be owned by uid %d"), path, ROOT_UID);
! 103: goto done;
! 104: }
! 105: if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
! 106: warningx(_("%s must only be writable by owner"), path);
! 107: goto done;
! 108: }
! 109:
! 110: /* Open plugin and map in symbol. */
! 111: group_handle = dlopen(path, RTLD_LAZY|RTLD_GLOBAL);
! 112: if (!group_handle) {
! 113: warningx(_("unable to dlopen %s: %s"), path, dlerror());
! 114: goto done;
! 115: }
! 116: group_plugin = dlsym(group_handle, "group_plugin");
! 117: if (group_plugin == NULL) {
! 118: warningx(_("unable to find symbol \"group_plugin\" in %s"), path);
! 119: goto done;
! 120: }
! 121:
! 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);
! 126: goto done;
! 127: }
! 128:
! 129: /*
! 130: * Split args into a vector if specified.
! 131: */
! 132: if (args != NULL) {
! 133: int ac = 0, wasblank = TRUE;
! 134: char *cp;
! 135:
! 136: for (cp = args; *cp != '\0'; cp++) {
! 137: if (isblank((unsigned char)*cp)) {
! 138: wasblank = TRUE;
! 139: } else if (wasblank) {
! 140: wasblank = FALSE;
! 141: ac++;
! 142: }
! 143: }
! 144: if (ac != 0) {
! 145: argv = emalloc2(ac, sizeof(char *));
! 146: ac = 0;
! 147: for ((cp = strtok(args, " \t")); cp; (cp = strtok(NULL, " \t")))
! 148: argv[ac++] = cp;
! 149: }
! 150: }
! 151:
! 152: rc = (group_plugin->init)(GROUP_API_VERSION, sudo_printf, argv);
! 153:
! 154: done:
! 155: efree(argv);
! 156:
! 157: if (rc != TRUE) {
! 158: if (group_handle != NULL) {
! 159: dlclose(group_handle);
! 160: group_handle = NULL;
! 161: group_plugin = NULL;
! 162: }
! 163: }
! 164:
! 165: return rc;
! 166: }
! 167:
! 168: void
! 169: group_plugin_unload(void)
! 170: {
! 171: if (group_plugin != NULL) {
! 172: (group_plugin->cleanup)();
! 173: group_plugin = NULL;
! 174: }
! 175: if (group_handle != NULL) {
! 176: dlclose(group_handle);
! 177: group_handle = NULL;
! 178: }
! 179: }
! 180:
! 181: int
! 182: group_plugin_query(const char *user, const char *group,
! 183: const struct passwd *pwd)
! 184: {
! 185: if (group_plugin == NULL)
! 186: return FALSE;
! 187: return (group_plugin->query)(user, group, pwd);
! 188: }
! 189:
! 190: #else /* !HAVE_DLOPEN && !HAVE_SHL_LOAD */
! 191:
! 192: /*
! 193: * No loadable shared object support.
! 194: */
! 195:
! 196: #ifndef FALSE
! 197: #define FALSE 0
! 198: #endif
! 199:
! 200: struct passwd;
! 201:
! 202: int
! 203: group_plugin_load(char *plugin_info)
! 204: {
! 205: return FALSE;
! 206: }
! 207:
! 208: void
! 209: group_plugin_unload(void)
! 210: {
! 211: return;
! 212: }
! 213:
! 214: int
! 215: group_plugin_query(const char *user, const char *group,
! 216: const struct passwd *pwd)
! 217: {
! 218: return FALSE;
! 219: }
! 220:
! 221: #endif /* HAVE_DLOPEN || HAVE_SHL_LOAD */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>