1 /* 2 * SPDX-License-Identifier: ISC 3 * 4 * Copyright (c) 2009-2020 Todd C. Miller <Todd.Miller@sudo.ws> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #ifndef SUDO_PLUGIN_H 20 #define SUDO_PLUGIN_H 21 22 /* API version major/minor */ 23 #define SUDO_API_VERSION_MAJOR 1 24 #define SUDO_API_VERSION_MINOR 17 25 #define SUDO_API_MKVERSION(x, y) (((x) << 16) | (y)) 26 #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR) 27 28 /* Getters and setters for plugin API versions */ 29 #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) 30 #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffffU) 31 #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \ 32 *(vp) = (*(vp) & 0x0000ffffU) | ((n) << 16); \ 33 } while(0) 34 #define SUDO_API_VERSION_SET_MINOR(vp, n) do { \ 35 *(vp) = (*(vp) & 0xffff0000U) | (n); \ 36 } while(0) 37 38 /* "plugin type" for the sudo front end, as passed to an audit plugin */ 39 #define SUDO_FRONT_END 0 40 41 /* Conversation function types and defines */ 42 struct sudo_conv_message { 43 #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ 44 #define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */ 45 #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ 46 #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ 47 #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ 48 #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ 49 #define SUDO_CONV_PREFER_TTY 0x2000 /* flag: use tty if possible */ 50 int msg_type; 51 int timeout; 52 const char *msg; 53 }; 54 55 /* 56 * Maximum length of a reply (not including the trailing NUL) when 57 * conversing with the user. In practical terms, this is the longest 58 * password sudo will support. This means that a buffer of size 59 * SUDO_CONV_REPL_MAX+1 is guaranteed to be able to hold any reply 60 * from the conversation function. 61 */ 62 #define SUDO_CONV_REPL_MAX 1023 63 64 struct sudo_conv_reply { 65 char *reply; 66 }; 67 68 /* Conversation callback API version major/minor */ 69 #define SUDO_CONV_CALLBACK_VERSION_MAJOR 1 70 #define SUDO_CONV_CALLBACK_VERSION_MINOR 0 71 #define SUDO_CONV_CALLBACK_VERSION SUDO_API_MKVERSION(SUDO_CONV_CALLBACK_VERSION_MAJOR, SUDO_CONV_CALLBACK_VERSION_MINOR) 72 73 /* 74 * Callback struct to be passed to the conversation function. 75 * Can be used to perform operations on suspend/resume such 76 * as dropping/acquiring locks. 77 */ 78 typedef int (*sudo_conv_callback_fn_t)(int signo, void *closure); 79 struct sudo_conv_callback { 80 unsigned int version; 81 void *closure; 82 sudo_conv_callback_fn_t on_suspend; 83 sudo_conv_callback_fn_t on_resume; 84 }; 85 86 typedef int (*sudo_conv_t)(int num_msgs, const struct sudo_conv_message msgs[], 87 struct sudo_conv_reply replies[], struct sudo_conv_callback *callback); 88 typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...); 89 90 /* 91 * Hooks allow a plugin to hook into specific sudo and/or libc functions. 92 */ 93 94 #if defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4) 95 # pragma GCC diagnostic ignored "-Wstrict-prototypes" 96 #endif 97 98 /* Hook functions typedefs. */ 99 typedef int (*sudo_hook_fn_t)(); 100 typedef int (*sudo_hook_fn_setenv_t)(const char *name, const char *value, int overwrite, void *closure); 101 typedef int (*sudo_hook_fn_putenv_t)(char *string, void *closure); 102 typedef int (*sudo_hook_fn_getenv_t)(const char *name, char **value, void *closure); 103 typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, void *closure); 104 105 /* Hook structure definition. */ 106 struct sudo_hook { 107 unsigned int hook_version; 108 unsigned int hook_type; 109 sudo_hook_fn_t hook_fn; 110 void *closure; 111 }; 112 113 /* Hook API version major/minor */ 114 #define SUDO_HOOK_VERSION_MAJOR 1 115 #define SUDO_HOOK_VERSION_MINOR 0 116 #define SUDO_HOOK_VERSION SUDO_API_MKVERSION(SUDO_HOOK_VERSION_MAJOR, SUDO_HOOK_VERSION_MINOR) 117 118 /* 119 * Hook function return values. 120 */ 121 #define SUDO_HOOK_RET_ERROR -1 /* error */ 122 #define SUDO_HOOK_RET_NEXT 0 /* go to the next hook in the list */ 123 #define SUDO_HOOK_RET_STOP 1 /* stop hook processing for this type */ 124 125 /* 126 * Hooks for setenv/unsetenv/putenv/getenv. 127 * This allows the plugin to be notified when a PAM module modifies 128 * the environment so it can update the copy of the environment that 129 * is passed to execve(). 130 */ 131 #define SUDO_HOOK_SETENV 1 132 #define SUDO_HOOK_UNSETENV 2 133 #define SUDO_HOOK_PUTENV 3 134 #define SUDO_HOOK_GETENV 4 135 136 /* 137 * Plugin interface to sudo's main event loop. 138 */ 139 typedef void (*sudo_plugin_ev_callback_t)(int fd, int what, void *closure); 140 141 struct timespec; 142 struct sudo_plugin_event { 143 int (*set)(struct sudo_plugin_event *pev, int fd, int events, sudo_plugin_ev_callback_t callback, void *closure); 144 int (*add)(struct sudo_plugin_event *pev, struct timespec *timeout); 145 int (*del)(struct sudo_plugin_event *pev); 146 int (*pending)(struct sudo_plugin_event *pev, int events, struct timespec *ts); 147 int (*fd)(struct sudo_plugin_event *pev); 148 void (*setbase)(struct sudo_plugin_event *pev, void *base); 149 void (*loopbreak)(struct sudo_plugin_event *pev); 150 void (*free)(struct sudo_plugin_event *pev); 151 /* actually larger... */ 152 }; 153 154 /* Sudo plugin Event types */ 155 #define SUDO_PLUGIN_EV_TIMEOUT 0x01 /* fire after timeout */ 156 #define SUDO_PLUGIN_EV_READ 0x02 /* fire when readable */ 157 #define SUDO_PLUGIN_EV_WRITE 0x04 /* fire when writable */ 158 #define SUDO_PLUGIN_EV_PERSIST 0x08 /* persist until deleted */ 159 #define SUDO_PLUGIN_EV_SIGNAL 0x10 /* fire on signal receipt */ 160 161 /* Policy plugin type and defines. */ 162 struct passwd; 163 struct policy_plugin { 164 #define SUDO_POLICY_PLUGIN 1 165 unsigned int type; /* always SUDO_POLICY_PLUGIN */ 166 unsigned int version; /* always SUDO_API_VERSION */ 167 int (*open)(unsigned int version, sudo_conv_t conversation, 168 sudo_printf_t sudo_printf, char * const settings[], 169 char * const user_info[], char * const user_env[], 170 char * const plugin_options[], const char **errstr); 171 void (*close)(int exit_status, int error); /* wait status or error */ 172 int (*show_version)(int verbose); 173 int (*check_policy)(int argc, char * const argv[], 174 char *env_add[], char **command_info[], 175 char **argv_out[], char **user_env_out[], const char **errstr); 176 int (*list)(int argc, char * const argv[], int verbose, 177 const char *list_user, const char **errstr); 178 int (*validate)(const char **errstr); 179 void (*invalidate)(int remove); 180 int (*init_session)(struct passwd *pwd, char **user_env_out[], 181 const char **errstr); 182 void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook)); 183 void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); 184 struct sudo_plugin_event * (*event_alloc)(void); 185 }; 186 187 /* I/O plugin type and defines. */ 188 struct io_plugin { 189 #define SUDO_IO_PLUGIN 2 190 unsigned int type; /* always SUDO_IO_PLUGIN */ 191 unsigned int version; /* always SUDO_API_VERSION */ 192 int (*open)(unsigned int version, sudo_conv_t conversation, 193 sudo_printf_t sudo_printf, char * const settings[], 194 char * const user_info[], char * const command_info[], 195 int argc, char * const argv[], char * const user_env[], 196 char * const plugin_options[], const char **errstr); 197 void (*close)(int exit_status, int error); /* wait status or error */ 198 int (*show_version)(int verbose); 199 int (*log_ttyin)(const char *buf, unsigned int len, const char **errstr); 200 int (*log_ttyout)(const char *buf, unsigned int len, const char **errstr); 201 int (*log_stdin)(const char *buf, unsigned int len, const char **errstr); 202 int (*log_stdout)(const char *buf, unsigned int len, const char **errstr); 203 int (*log_stderr)(const char *buf, unsigned int len, const char **errstr); 204 void (*register_hooks)(int version, 205 int (*register_hook)(struct sudo_hook *hook)); 206 void (*deregister_hooks)(int version, 207 int (*deregister_hook)(struct sudo_hook *hook)); 208 int (*change_winsize)(unsigned int line, unsigned int cols, 209 const char **errstr); 210 int (*log_suspend)(int signo, const char **errstr); 211 struct sudo_plugin_event * (*event_alloc)(void); 212 }; 213 214 /* Differ audit plugin close status types. */ 215 #define SUDO_PLUGIN_NO_STATUS 0 216 #define SUDO_PLUGIN_WAIT_STATUS 1 217 #define SUDO_PLUGIN_EXEC_ERROR 2 218 #define SUDO_PLUGIN_SUDO_ERROR 3 219 220 /* Audit plugin type and defines */ 221 struct audit_plugin { 222 #define SUDO_AUDIT_PLUGIN 3 223 unsigned int type; /* always SUDO_AUDIT_PLUGIN */ 224 unsigned int version; /* always SUDO_API_VERSION */ 225 int (*open)(unsigned int version, sudo_conv_t conversation, 226 sudo_printf_t sudo_printf, char * const settings[], 227 char * const user_info[], int submit_optind, 228 char * const submit_argv[], char * const submit_envp[], 229 char * const plugin_options[], const char **errstr); 230 void (*close)(int status_type, int status); 231 int (*accept)(const char *plugin_name, unsigned int plugin_type, 232 char * const command_info[], char * const run_argv[], 233 char * const run_envp[], const char **errstr); 234 int (*reject)(const char *plugin_name, unsigned int plugin_type, 235 const char *audit_msg, char * const command_info[], 236 const char **errstr); 237 int (*error)(const char *plugin_name, unsigned int plugin_type, 238 const char *audit_msg, char * const command_info[], 239 const char **errstr); 240 int (*show_version)(int verbose); 241 void (*register_hooks)(int version, int (*register_hook)(struct sudo_hook *hook)); 242 void (*deregister_hooks)(int version, int (*deregister_hook)(struct sudo_hook *hook)); 243 struct sudo_plugin_event * (*event_alloc)(void); 244 }; 245 246 /* Approval plugin type and defines */ 247 struct approval_plugin { 248 #define SUDO_APPROVAL_PLUGIN 4 249 unsigned int type; /* always SUDO_APPROVAL_PLUGIN */ 250 unsigned int version; /* always SUDO_API_VERSION */ 251 int (*open)(unsigned int version, sudo_conv_t conversation, 252 sudo_printf_t sudo_printf, char * const settings[], 253 char * const user_info[], int submit_optind, 254 char * const submit_argv[], char * const submit_envp[], 255 char * const plugin_options[], const char **errstr); 256 void (*close)(void); 257 int (*check)(char * const command_info[], char * const run_argv[], 258 char * const run_envp[], const char **errstr); 259 int (*show_version)(int verbose); 260 }; 261 262 /* Sudoers group plugin version major/minor */ 263 #define GROUP_API_VERSION_MAJOR 1 264 #define GROUP_API_VERSION_MINOR 0 265 #define GROUP_API_VERSION SUDO_API_MKVERSION(GROUP_API_VERSION_MAJOR, GROUP_API_VERSION_MINOR) 266 267 /* Getters and setters for group version (for source compat only) */ 268 #define GROUP_API_VERSION_GET_MAJOR(v) SUDO_API_VERSION_GET_MAJOR(v) 269 #define GROUP_API_VERSION_GET_MINOR(v) SUDO_API_VERSION_GET_MINOR(v) 270 #define GROUP_API_VERSION_SET_MAJOR(vp, n) SUDO_API_VERSION_SET_MAJOR(vp, n) 271 #define GROUP_API_VERSION_SET_MINOR(vp, n) SUDO_API_VERSION_SET_MINOR(vp, n) 272 273 /* 274 * version: for compatibility checking 275 * group_init: return 1 on success, 0 if unconfigured, -1 on error. 276 * group_cleanup: called to clean up resources used by provider 277 * user_in_group: returns 1 if user is in group, 0 if not. 278 * note that pwd may be NULL if the user is not in passwd. 279 */ 280 struct sudoers_group_plugin { 281 unsigned int version; 282 int (*init)(int version, sudo_printf_t sudo_printf, char *const argv[]); 283 void (*cleanup)(void); 284 int (*query)(const char *user, const char *group, const struct passwd *pwd); 285 }; 286 287 #endif /* SUDO_PLUGIN_H */ 288