Return to group_plugin.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers |
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 */