--- embedaddon/sudo/doc/sudo_plugin.cat 2012/02/21 16:23:02 1.1.1.1 +++ embedaddon/sudo/doc/sudo_plugin.cat 2012/05/29 12:26:49 1.1.1.2 @@ -32,8 +32,8 @@ DDEESSCCRRIIPPTTIIOONN io_plugin in the plugin shared object. The _p_a_t_h may be fully qualified or relative. If not fully qualified it is relative to the _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c directory. Any additional parameters after the _p_a_t_h - are ignored. Lines that don't begin with Plugin or Path are silently - ignored. + are passed as options to the plugin's _o_p_e_n function. Lines that don't + begin with Plugin, Path, Debug or Set are silently ignored. The same shared object may contain multiple plugins, each with a different symbol name. The shared object file must be owned by uid 0 @@ -45,13 +45,17 @@ DDEESSCCRRIIPPTTIIOONN # Default /etc/sudo.conf file # # Format: - # Plugin plugin_name plugin_path + # Plugin plugin_name plugin_path plugin_options ... # Path askpass /path/to/askpass + # Path noexec /path/to/sudo_noexec.so + # Debug sudo /var/log/sudo_debug all@warn + # Set disable_coredump true # # The plugin_path is relative to /usr/local/libexec unless # fully qualified. # The plugin_name corresponds to a global symbol in the plugin # that contains the plugin interface structure. + # The plugin_options are optional. # Plugin sudoers_policy sudoers.so Plugin sudoers_io sudoers.so @@ -69,7 +73,8 @@ DDEESSCCRRIIPPTTIIOONN unsigned int version; /* always SUDO_API_VERSION */ int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t plugin_printf, char * const settings[], - char * const user_info[], char * const user_env[]); + char * const user_info[], char * const user_env[], + char * const plugin_options[]); void (*close)(int exit_status, int error); int (*show_version)(int verbose); int (*check_policy)(int argc, char * const argv[], @@ -79,7 +84,11 @@ DDEESSCCRRIIPPTTIIOONN const char *list_user); int (*validate)(void); void (*invalidate)(int remove); - int (*init_session)(struct passwd *pwd); + int (*init_session)(struct passwd *pwd, char **user_env[]); + void (*register_hooks)(int version, + int (*register_hook)(struct sudo_hook *hook)); + void (*deregister_hooks)(int version, + int (*deregister_hook)(struct sudo_hook *hook)); }; The policy_plugin struct has the following fields: @@ -96,7 +105,8 @@ DDEESSCCRRIIPPTTIIOONN open int (*open)(unsigned int version, sudo_conv_t conversation, sudo_printf_t plugin_printf, char * const settings[], - char * const user_info[], char * const user_env[]); + char * const user_info[], char * const user_env[], + char * const plugin_options[]); Returns 1 on success, 0 on failure, -1 if a general error occurred, or -2 if there was a usage error. In the latter case, ssuuddoo will @@ -133,9 +143,31 @@ DDEESSCCRRIIPPTTIIOONN equal sign ('=') since the _n_a_m_e field will never include one itself but the _v_a_l_u_e might. + debug_flags=string + A comma-separated list of debug flags that correspond to + ssuuddoo's Debug entry in _/_e_t_c_/_s_u_d_o_._c_o_n_f, if there is one. The + flags are passed to the plugin as they appear in + _/_e_t_c_/_s_u_d_o_._c_o_n_f. The syntax used by ssuuddoo and the _s_u_d_o_e_r_s + plugin is _s_u_b_s_y_s_t_e_m@_p_r_i_o_r_i_t_y but the plugin is free to use + a different format so long as it does not include a command + ,. + + For reference, the priorities supported by the ssuuddoo front + end and _s_u_d_o_e_r_s are: _c_r_i_t, _e_r_r, _w_a_r_n, _n_o_t_i_c_e, _d_i_a_g, _i_n_f_o, + _t_r_a_c_e and _d_e_b_u_g. + + The following subsystems are defined: _m_a_i_n, _m_e_m_o_r_y, _a_r_g_s, + _e_x_e_c, _p_t_y, _u_t_m_p, _c_o_n_v, _p_c_o_m_m, _u_t_i_l, _l_i_s_t, _n_e_t_i_f, _a_u_d_i_t, + _e_d_i_t, _s_e_l_i_n_u_x, _l_d_a_p, _m_a_t_c_h, _p_a_r_s_e_r, _a_l_i_a_s, _d_e_f_a_u_l_t_s, _a_u_t_h, + _e_n_v, _l_o_g_g_i_n_g, _n_s_s, _r_b_t_r_e_e, _p_e_r_m_s, _p_l_u_g_i_n. The subsystem + _a_l_l includes every subsystem. + + There is not currently a way to specify a set of debug + flags specific to the plugin--the flags are shared by ssuuddoo + and the plugin. + debug_level=number - A numeric debug level, from 1-9, if specified via the -D - flag. + This setting has been deprecated in favor of _d_e_b_u_g___f_l_a_g_s. runas_user=string The user name or uid to to run the command as, if specified @@ -244,12 +276,41 @@ DDEESSCCRRIIPPTTIIOONN equal sign ('=') since the _n_a_m_e field will never include one itself but the _v_a_l_u_e might. + pid=int + The process ID of the running ssuuddoo process. Only available + starting with API version 1.2 + + ppid=int + The parent process ID of the running ssuuddoo process. Only + available starting with API version 1.2 + + sid=int + The session ID of the running ssuuddoo process or 0 if ssuuddoo is + not part of a POSIX job control session. Only available + starting with API version 1.2 + + pgid=int + The ID of the process group that the running ssuuddoo process + belongs to. Only available starting with API version 1.2 + + tcpgid=int + The ID of the forground process group associated with the + terminal device associcated with the ssuuddoo process or -1 if + there is no terminal present. Only available starting with + API version 1.2 + user=string The name of the user invoking ssuuddoo. + euid=uid_t + The effective user ID of the user invoking ssuuddoo. + uid=uid_t The real user ID of the user invoking ssuuddoo. + egid=gid_t + The effective group ID of the user invoking ssuuddoo. + gid=gid_t The real group ID of the user invoking ssuuddoo. @@ -287,6 +348,18 @@ DDEESSCCRRIIPPTTIIOONN equal sign ('=') since the _n_a_m_e field will never include one itself but the _v_a_l_u_e might. + plugin_options + Any (non-comment) strings immediately after the plugin path are + treated as arguments to the plugin. These arguments are split + on a white space boundary and are passed to the plugin in the + form of a NULL-terminated array of strings. If no arguments + were specified, _p_l_u_g_i_n___o_p_t_i_o_n_s will be the NULL pointer. + + NOTE: the _p_l_u_g_i_n___o_p_t_i_o_n_s parameter is only available starting + with API version 1.2. A plugin mmuusstt check the API version + specified by the ssuuddoo front end before using _p_l_u_g_i_n___o_p_t_i_o_n_s. + Failure to do so may result in a crash. + close void (*close)(int exit_status, int error); @@ -583,25 +656,93 @@ DDEESSCCRRIIPPTTIIOONN support credential caching. init_session - int (*init_session)(struct passwd *pwd); + int (*init_session)(struct passwd *pwd, char **user_envp[); - The init_session function is called when ssuuddoo sets up the execution - environment for the command, immediately before the contents of the - _c_o_m_m_a_n_d___i_n_f_o list are applied (before the uid changes). This can - be used to do session setup that is not supported by _c_o_m_m_a_n_d___i_n_f_o, - such as opening the PAM session. + The init_session function is called before ssuuddoo sets up the + execution environment for the command. It is run in the parent + ssuuddoo process and before any uid or gid changes. This can be used + to perform session setup that is not supported by _c_o_m_m_a_n_d___i_n_f_o, + such as opening the PAM session. The close function can be used to + tear down the session that was opened by init_session. The _p_w_d argument points to a passwd struct for the user the command will be run as if the uid the command will run as was found in the password database, otherwise it will be NULL. + The _u_s_e_r___e_n_v argument points to the environment the command will + run in, in the form of a NULL-terminated vector of "name=value" + strings. This is the same string passed back to the front end via + the Policy Plugin's _u_s_e_r___e_n_v___o_u_t parameter. If the init_session + function needs to modify the user environment, it should update the + pointer stored in _u_s_e_r___e_n_v. The expected use case is to merge the + contents of the PAM environment (if any) with the contents of + _u_s_e_r___e_n_v. NOTE: the _u_s_e_r___e_n_v parameter is only available starting + with API version 1.2. A plugin mmuusstt check the API version + specified by the ssuuddoo front end before using _u_s_e_r___e_n_v. Failure to + do so may result in a crash. + Returns 1 on success, 0 on failure and -1 on error. On error, the plugin may optionally call the conversation or plugin_printf function with SUDO_CONF_ERROR_MSG to present additional error information to the user. - _V_e_r_s_i_o_n _m_a_c_r_o_s + register_hooks + void (*register_hooks)(int version, + int (*register_hook)(struct sudo_hook *hook)); + The register_hooks function is called by the sudo front end to + register any hooks the plugin needs. If the plugin does not + support hooks, register_hooks should be set to the NULL pointer. + + The _v_e_r_s_i_o_n argument describes the version of the hooks API + supported by the ssuuddoo front end. + + The register_hook function should be used to register any supported + hooks the plugin needs. It returns 0 on success, 1 if the hook + type is not supported and -1 if the major version in struct hook + does not match the front end's major hook API version. + + See the "Hook Function API" section below for more information + about hooks. + + NOTE: the register_hooks function is only available starting with + API version 1.2. If the ssuuddoo front end doesn't support API version + 1.2 or higher, register_hooks will not be called. + + deregister_hooks + void (*deregister_hooks)(int version, + int (*deregister_hook)(struct sudo_hook *hook)); + + The deregister_hooks function is called by the sudo front end to + deregister any hooks the plugin has registered. If the plugin does + not support hooks, deregister_hooks should be set to the NULL + pointer. + + The _v_e_r_s_i_o_n argument describes the version of the hooks API + supported by the ssuuddoo front end. + + The deregister_hook function should be used to deregister any hooks + that were put in place by the register_hook function. If the + plugin tries to deregister a hook that the front end does not + support, deregister_hook will return an error. + + See the "Hook Function API" section below for more information + about hooks. + + NOTE: the deregister_hooks function is only available starting with + API version 1.2. If the ssuuddoo front end doesn't support API version + 1.2 or higher, deregister_hooks will not be called. + + _P_o_l_i_c_y _P_l_u_g_i_n _V_e_r_s_i_o_n _M_a_c_r_o_s + + /* Plugin API version major/minor. */ + #define SUDO_API_VERSION_MAJOR 1 + #define SUDO_API_VERSION_MINOR 2 + #define SUDO_API_MKVERSION(x, y) ((x << 16) | y) + #define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR,\ + SUDO_API_VERSION_MINOR) + + /* Getters and setters for API version */ #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \ @@ -611,11 +752,6 @@ DDEESSCCRRIIPPTTIIOONN *(vp) = (*(vp) & 0xffff0000) | (n); \ } while(0) - #define SUDO_API_VERSION_MAJOR 1 - #define SUDO_API_VERSION_MINOR 0 - #define SUDO_API_VERSION ((SUDO_API_VERSION_MAJOR << 16) | \ - SUDO_API_VERSION_MINOR) - II//OO PPlluuggiinn AAPPII struct io_plugin { #define SUDO_IO_PLUGIN 2 @@ -624,7 +760,7 @@ DDEESSCCRRIIPPTTIIOONN int (*open)(unsigned int version, sudo_conv_t conversation sudo_printf_t plugin_printf, char * const settings[], char * const user_info[], int argc, char * const argv[], - char * const user_env[]); + char * const user_env[], char * const plugin_options[]); void (*close)(int exit_status, int error); /* wait status or error */ int (*show_version)(int verbose); int (*log_ttyin)(const char *buf, unsigned int len); @@ -632,6 +768,10 @@ DDEESSCCRRIIPPTTIIOONN int (*log_stdin)(const char *buf, unsigned int len); int (*log_stdout)(const char *buf, unsigned int len); int (*log_stderr)(const char *buf, unsigned int len); + void (*register_hooks)(int version, + int (*register_hook)(struct sudo_hook *hook)); + void (*deregister_hooks)(int version, + int (*deregister_hook)(struct sudo_hook *hook)); }; When an I/O plugin is loaded, ssuuddoo runs the command in a pseudo-tty. @@ -667,7 +807,7 @@ DDEESSCCRRIIPPTTIIOONN int (*open)(unsigned int version, sudo_conv_t conversation sudo_printf_t plugin_printf, char * const settings[], char * const user_info[], int argc, char * const argv[], - char * const user_env[]); + char * const user_env[], char * const plugin_options[]); The _o_p_e_n function is run before the _l_o_g___i_n_p_u_t, _l_o_g___o_u_t_p_u_t or _s_h_o_w___v_e_r_s_i_o_n functions are called. It is only called if the @@ -744,6 +884,18 @@ DDEESSCCRRIIPPTTIIOONN equal sign ('=') since the _n_a_m_e field will never include one itself but the _v_a_l_u_e might. + plugin_options + Any (non-comment) strings immediately after the plugin path are + treated as arguments to the plugin. These arguments are split + on a white space boundary and are passed to the plugin in the + form of a NULL-terminated array of strings. If no arguments + were specified, _p_l_u_g_i_n___o_p_t_i_o_n_s will be the NULL pointer. + + NOTE: the _p_l_u_g_i_n___o_p_t_i_o_n_s parameter is only available starting + with API version 1.2. A plugin mmuusstt check the API version + specified by the ssuuddoo front end before using _p_l_u_g_i_n___o_p_t_i_o_n_s. + Failure to do so may result in a crash. + close void (*close)(int exit_status, int error); @@ -854,10 +1006,153 @@ DDEESSCCRRIIPPTTIIOONN len The length of _b_u_f in bytes. - _V_e_r_s_i_o_n _m_a_c_r_o_s + register_hooks + See the "Policy Plugin API" section for a description of + register_hooks. + deregister_hooks + See the "Policy Plugin API" section for a description of + deregister_hooks. + + _I_/_O _P_l_u_g_i_n _V_e_r_s_i_o_n _M_a_c_r_o_s + Same as for the "Policy Plugin API". + HHooookk FFuunnccttiioonn AAPPII + Beginning with plugin API version 1.2, it is possible to install hooks + for certain functions called by the ssuuddoo front end. + + Currently, the only supported hooks relate to the handling of + environment variables. Hooks can be used to intercept attempts to get, + set, or remove environment variables so that these changes can be + reflected in the version of the environment that is used to execute a + command. A future version of the API will support hooking internal + ssuuddoo front end functions as well. + + _H_o_o_k _s_t_r_u_c_t_u_r_e + + Hooks in ssuuddoo are described by the following structure: + + typedef int (*sudo_hook_fn_t)(); + + struct sudo_hook { + int hook_version; + int hook_type; + sudo_hook_fn_t hook_fn; + void *closure; + }; + + The sudo_hook structure has the following fields: + + hook_version + The hook_version field should be set to SUDO_HOOK_VERSION. + + hook_type + The hook_type field may be one of the following supported hook + types: + + SUDO_HOOK_SETENV + The C library setenv() function. Any registered hooks will run + before the C library implementation. The hook_fn field should + be a function that matches the following typedef: + + typedef int (*sudo_hook_fn_setenv_t)(const char *name, + const char *value, int overwrite, void *closure); + + If the registered hook does not match the typedef the results + are unspecified. + + SUDO_HOOK_UNSETENV + The C library unsetenv() function. Any registered hooks will + run before the C library implementation. The hook_fn field + should be a function that matches the following typedef: + + typedef int (*sudo_hook_fn_unsetenv_t)(const char *name, + void *closure); + + SUDO_HOOK_GETENV + The C library getenv() function. Any registered hooks will run + before the C library implementation. The hook_fn field should + be a function that matches the following typedef: + + typedef int (*sudo_hook_fn_getenv_t)(const char *name, + char **value, void *closure); + + If the registered hook does not match the typedef the results + are unspecified. + + SUDO_HOOK_PUTENV + The C library putenv() function. Any registered hooks will run + before the C library implementation. The hook_fn field should + be a function that matches the following typedef: + + typedef int (*sudo_hook_fn_putenv_t)(char *string, + void *closure); + + If the registered hook does not match the typedef the results + are unspecified. + + hook_fn + sudo_hook_fn_t hook_fn; + + The hook_fn field should be set to the plugin's hook + implementation. The actual function arguments will vary depending + on the hook_type (see hook_type above). In all cases, the closure + field of struct sudo_hook is passed as the last function parameter. + This can be used to pass arbitrary data to the plugin's hook + implementation. + + The function return value may be one of the following: + + SUDO_HOOK_RET_ERROR + The hook function encountered an error. + + SUDO_HOOK_RET_NEXT + The hook completed without error, go on to the next hook + (including the native implementation if applicable). For + example, a getenv hook might return SUDO_HOOK_RET_NEXT if the + specified variable was not found in the private copy of the + environment. + + SUDO_HOOK_RET_STOP + The hook completed without error, stop processing hooks for + this invocation. This can be used to replace the native + implementation. For example, a setenv hook that operates on a + private copy of the environment but leaves environ unchanged. + + Note that it is very easy to create an infinite loop when hooking C + library functions. For example, a getenv hook that calls the snprintf + function may create a loop if the snprintf implementation calls getenv + to check the locale. To prevent this, you may wish to use a static + variable in the hook function to guard against nested calls. E.g. + + static int in_progress = 0; /* avoid recursion */ + if (in_progress) + return SUDO_HOOK_RET_NEXT; + in_progress = 1; + ... + in_progress = 0; + return SUDO_HOOK_RET_STOP; + + _H_o_o_k _A_P_I _V_e_r_s_i_o_n _M_a_c_r_o_s + + /* Hook API version major/minor */ + #define SUDO_HOOK_VERSION_MAJOR 1 + #define SUDO_HOOK_VERSION_MINOR 0 + #define SUDO_HOOK_MKVERSION(x, y) ((x << 16) | y) + #define SUDO_HOOK_VERSION SUDO_HOOK_MKVERSION(SUDO_HOOK_VERSION_MAJOR,\ + SUDO_HOOK_VERSION_MINOR) + + /* Getters and setters for hook API version */ + #define SUDO_HOOK_VERSION_GET_MAJOR(v) ((v) >> 16) + #define SUDO_HOOK_VERSION_GET_MINOR(v) ((v) & 0xffff) + #define SUDO_HOOK_VERSION_SET_MAJOR(vp, n) do { \ + *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \ + } while(0) + #define SUDO_HOOK_VERSION_SET_MINOR(vp, n) do { \ + *(vp) = (*(vp) & 0xffff0000) | (n); \ + } while(0) + CCoonnvveerrssaattiioonn AAPPII If the plugin needs to interact with the user, it may do so via the conversation function. A plugin should not attempt to read directly @@ -875,6 +1170,7 @@ DDEESSCCRRIIPPTTIIOONN #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ + #define SUDO_CONV_DEBUG_MSG 0x0006 /* debugging message */ #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ int msg_type; int timeout; @@ -901,11 +1197,18 @@ DDEESSCCRRIIPPTTIIOONN buffer filled in to the struct sudo_conv_reply, if any. The printf-style function uses the same underlying mechanism as the - conversation function but only supports SUDO_CONV_INFO_MSG and - SUDO_CONV_ERROR_MSG for the _m_s_g___t_y_p_e parameter. It can be more - convenient than using the conversation function if no user reply is - needed and supports standard _p_r_i_n_t_f_(_) escape sequences. + conversation function but only supports SUDO_CONV_INFO_MSG, + SUDO_CONV_ERROR_MSG and SUDO_CONV_DEBUG_MSG for the _m_s_g___t_y_p_e parameter. + It can be more convenient than using the conversation function if no + user reply is needed and supports standard _p_r_i_n_t_f_(_) escape sequences. + Unlike, SUDO_CONV_INFO_MSG and SUDO_CONV_ERROR_MSG, messages sent with + the _m_s_g___t_y_p_e are not directly user-visible. + Instead, they are logged to the file specified in the Debug statement + (if any) in the _/_e_t_c_/_s_u_d_o_._c_o_n_f file. This allows a plugin to log + debugging information and is intended to be used in conjunction with + the _d_e_b_u_g___f_l_a_g_s setting. + See the sample plugin for an example of the conversation function usage. @@ -991,7 +1294,7 @@ DDEESSCCRRIIPPTTIIOONN pwd The password database entry for _u_s_e_r, if any. If _u_s_e_r is not present in the password database, _p_w_d will be NULL. - _V_e_r_s_i_o_n _M_a_c_r_o_s + _G_r_o_u_p _A_P_I _V_e_r_s_i_o_n _M_a_c_r_o_s /* Sudoers group plugin version major/minor */ #define GROUP_API_VERSION_MAJOR 1 @@ -1009,6 +1312,28 @@ DDEESSCCRRIIPPTTIIOONN *(vp) = (*(vp) & 0xffff0000) | (n); \ } while(0) +PPLLUUGGIINN AAPPII CCHHAANNGGEELLOOGG + The following revisions have been made to the Sudo Plugin API. + + Version 1.0 + Initial API version. + + Version 1.1 + The I/O logging plugin's open function was modified to take the + command_info list as an argument. + + Version 1.2 + The Policy and I/O logging plugins' open functions are now passed a + list of plugin options if any are specified in _/_e_t_c_/_s_u_d_o_._c_o_n_f. + + A simple hooks API has been introduced to allow plugins to hook in + to the system's environment handling functions. + + The init_session Policy plugin function is now passed a pointer to + the user environment which can be updated as needed. This can be + used to merge in environment variables stored in the PAM handle + before a command is run. + SSEEEE AALLSSOO _s_u_d_o_e_r_s(4), _s_u_d_o(1m) @@ -1030,4 +1355,4 @@ DDIISSCCLLAAIIMMEERR -1.8.3 September 16, 2011 SUDO_PLUGIN(1m) +1.8.5 April 23, 2012 SUDO_PLUGIN(1m)