context: add XKB_CONTEXT_NO_SECURE_GETENV flag (#312)
This flag is useful for clients that may have relatively benign capabilities set, like CAP_SYS_NICE, that also want to use the xkb configuration from the environment and user configs in XDG_CONFIG_HOME. Fixes: https://github.com/xkbcommon/libxkbcommon/issues/308 Fixes: https://github.com/xkbcommon/libxkbcommon/issues/129 Signed-off-by: Ran Benita <ran@unusedvar.com>master
parent
9d1043dcb5
commit
b4e81ca172
|
@ -580,9 +580,17 @@ enum xkb_context_flags {
|
|||
XKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0),
|
||||
/**
|
||||
* Don't take RMLVO names from the environment.
|
||||
*
|
||||
* @since 0.3.0
|
||||
*/
|
||||
XKB_CONTEXT_NO_ENVIRONMENT_NAMES = (1 << 1)
|
||||
XKB_CONTEXT_NO_ENVIRONMENT_NAMES = (1 << 1),
|
||||
/**
|
||||
* Disable the use of secure_getenv for this context, so that privileged
|
||||
* processes can use environment variables. Client uses at their own risk.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
XKB_CONTEXT_NO_SECURE_GETENV = (1 << 2)
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -163,6 +163,13 @@ enum rxkb_context_flags {
|
|||
* on the lookup behavior.
|
||||
*/
|
||||
RXKB_CONTEXT_LOAD_EXOTIC_RULES = (1 << 1),
|
||||
/**
|
||||
* Disable the use of secure_getenv for this context, so that privileged
|
||||
* processes can use environment variables. Client uses at their own risk.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*/
|
||||
RXKB_CONTEXT_NO_SECURE_GETENV = (1 << 2)
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -262,7 +262,7 @@ lex_include_string(struct scanner *s, struct xkb_compose_table *table,
|
|||
scanner_buf_append(s, '%');
|
||||
}
|
||||
else if (scanner_chr(s, 'H')) {
|
||||
const char *home = secure_getenv("HOME");
|
||||
const char *home = xkb_context_getenv(table->ctx, "HOME");
|
||||
if (!home) {
|
||||
scanner_err(s, "%%H was used in an include statement, but the HOME environment variable is not set");
|
||||
return TOK_ERROR;
|
||||
|
@ -273,7 +273,7 @@ lex_include_string(struct scanner *s, struct xkb_compose_table *table,
|
|||
}
|
||||
}
|
||||
else if (scanner_chr(s, 'L')) {
|
||||
char *path = get_locale_compose_file_path(table->locale);
|
||||
char *path = get_locale_compose_file_path(table->ctx, table->locale);
|
||||
if (!path) {
|
||||
scanner_err(s, "failed to expand %%L to the locale Compose file");
|
||||
return TOK_ERROR;
|
||||
|
@ -286,7 +286,7 @@ lex_include_string(struct scanner *s, struct xkb_compose_table *table,
|
|||
free(path);
|
||||
}
|
||||
else if (scanner_chr(s, 'S')) {
|
||||
const char *xlocaledir = get_xlocaledir_path();
|
||||
const char *xlocaledir = get_xlocaledir_path(table->ctx);
|
||||
if (!scanner_buf_appends(s, xlocaledir)) {
|
||||
scanner_err(s, "include path after expanding %%S is too long");
|
||||
return TOK_ERROR;
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include "xkbcommon/xkbcommon.h"
|
||||
#include "utils.h"
|
||||
#include "context.h"
|
||||
#include "paths.h"
|
||||
#include "utils.h"
|
||||
|
||||
enum resolve_name_direction {
|
||||
LEFT_TO_RIGHT,
|
||||
|
@ -33,9 +34,9 @@ enum resolve_name_direction {
|
|||
};
|
||||
|
||||
const char *
|
||||
get_xlocaledir_path(void)
|
||||
get_xlocaledir_path(struct xkb_context *ctx)
|
||||
{
|
||||
const char *dir = secure_getenv("XLOCALEDIR");
|
||||
const char *dir = xkb_context_getenv(ctx, "XLOCALEDIR");
|
||||
if (!dir)
|
||||
dir = XLOCALEDIR;
|
||||
return dir;
|
||||
|
@ -47,8 +48,8 @@ get_xlocaledir_path(void)
|
|||
* @filename is relative to the xlocaledir.
|
||||
*/
|
||||
static char *
|
||||
resolve_name(const char *filename, enum resolve_name_direction direction,
|
||||
const char *name)
|
||||
resolve_name(struct xkb_context *ctx, const char *filename,
|
||||
enum resolve_name_direction direction, const char *name)
|
||||
{
|
||||
int ret;
|
||||
bool ok;
|
||||
|
@ -62,7 +63,7 @@ resolve_name(const char *filename, enum resolve_name_direction direction,
|
|||
char *match;
|
||||
size_t left_len, right_len, name_len;
|
||||
|
||||
xlocaledir = get_xlocaledir_path();
|
||||
xlocaledir = get_xlocaledir_path(ctx);
|
||||
|
||||
ret = snprintf(path, sizeof(path), "%s/%s", xlocaledir, filename);
|
||||
if (ret < 0 || (size_t) ret >= sizeof(path))
|
||||
|
@ -137,27 +138,27 @@ resolve_name(const char *filename, enum resolve_name_direction direction,
|
|||
}
|
||||
|
||||
char *
|
||||
resolve_locale(const char *locale)
|
||||
resolve_locale(struct xkb_context *ctx, const char *locale)
|
||||
{
|
||||
char *alias = resolve_name("locale.alias", LEFT_TO_RIGHT, locale);
|
||||
char *alias = resolve_name(ctx, "locale.alias", LEFT_TO_RIGHT, locale);
|
||||
return alias ? alias : strdup(locale);
|
||||
}
|
||||
|
||||
char *
|
||||
get_xcomposefile_path(void)
|
||||
get_xcomposefile_path(struct xkb_context *ctx)
|
||||
{
|
||||
return strdup_safe(secure_getenv("XCOMPOSEFILE"));
|
||||
return strdup_safe(xkb_context_getenv(ctx, "XCOMPOSEFILE"));
|
||||
}
|
||||
|
||||
char *
|
||||
get_xdg_xcompose_file_path(void)
|
||||
get_xdg_xcompose_file_path(struct xkb_context *ctx)
|
||||
{
|
||||
const char *xdg_config_home;
|
||||
const char *home;
|
||||
|
||||
xdg_config_home = secure_getenv("XDG_CONFIG_HOME");
|
||||
xdg_config_home = xkb_context_getenv(ctx, "XDG_CONFIG_HOME");
|
||||
if (!xdg_config_home || xdg_config_home[0] != '/') {
|
||||
home = secure_getenv("HOME");
|
||||
home = xkb_context_getenv(ctx, "HOME");
|
||||
if (!home)
|
||||
return NULL;
|
||||
return asprintf_safe("%s/.config/XCompose", home);
|
||||
|
@ -167,11 +168,11 @@ get_xdg_xcompose_file_path(void)
|
|||
}
|
||||
|
||||
char *
|
||||
get_home_xcompose_file_path(void)
|
||||
get_home_xcompose_file_path(struct xkb_context *ctx)
|
||||
{
|
||||
const char *home;
|
||||
|
||||
home = secure_getenv("HOME");
|
||||
home = xkb_context_getenv(ctx, "HOME");
|
||||
if (!home)
|
||||
return NULL;
|
||||
|
||||
|
@ -179,7 +180,7 @@ get_home_xcompose_file_path(void)
|
|||
}
|
||||
|
||||
char *
|
||||
get_locale_compose_file_path(const char *locale)
|
||||
get_locale_compose_file_path(struct xkb_context *ctx, const char *locale)
|
||||
{
|
||||
char *resolved;
|
||||
char *path;
|
||||
|
@ -198,7 +199,7 @@ get_locale_compose_file_path(const char *locale)
|
|||
if (streq(locale, "C"))
|
||||
locale = "en_US.UTF-8";
|
||||
|
||||
resolved = resolve_name("compose.dir", RIGHT_TO_LEFT, locale);
|
||||
resolved = resolve_name(ctx, "compose.dir", RIGHT_TO_LEFT, locale);
|
||||
if (!resolved)
|
||||
return NULL;
|
||||
|
||||
|
@ -206,7 +207,7 @@ get_locale_compose_file_path(const char *locale)
|
|||
path = resolved;
|
||||
}
|
||||
else {
|
||||
const char *xlocaledir = get_xlocaledir_path();
|
||||
const char *xlocaledir = get_xlocaledir_path(ctx);
|
||||
path = asprintf_safe("%s/%s", xlocaledir, resolved);
|
||||
free(resolved);
|
||||
}
|
||||
|
|
|
@ -25,21 +25,21 @@
|
|||
#define COMPOSE_RESOLVE_H
|
||||
|
||||
char *
|
||||
resolve_locale(const char *locale);
|
||||
resolve_locale(struct xkb_context *ctx, const char *locale);
|
||||
|
||||
const char *
|
||||
get_xlocaledir_path(void);
|
||||
get_xlocaledir_path(struct xkb_context *ctx);
|
||||
|
||||
char *
|
||||
get_xcomposefile_path(void);
|
||||
get_xcomposefile_path(struct xkb_context *ctx);
|
||||
|
||||
char *
|
||||
get_xdg_xcompose_file_path(void);
|
||||
get_xdg_xcompose_file_path(struct xkb_context *ctx);
|
||||
|
||||
char *
|
||||
get_home_xcompose_file_path(void);
|
||||
get_home_xcompose_file_path(struct xkb_context *ctx);
|
||||
|
||||
char *
|
||||
get_locale_compose_file_path(const char *locale);
|
||||
get_locale_compose_file_path(struct xkb_context *ctx, const char *locale);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -38,7 +38,7 @@ xkb_compose_table_new(struct xkb_context *ctx,
|
|||
struct xkb_compose_table *table;
|
||||
struct compose_node dummy;
|
||||
|
||||
resolved_locale = resolve_locale(locale);
|
||||
resolved_locale = resolve_locale(ctx, locale);
|
||||
if (!resolved_locale)
|
||||
return NULL;
|
||||
|
||||
|
@ -174,7 +174,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
|
|||
if (!table)
|
||||
return NULL;
|
||||
|
||||
path = get_xcomposefile_path();
|
||||
path = get_xcomposefile_path(ctx);
|
||||
if (path) {
|
||||
file = fopen(path, "rb");
|
||||
if (file)
|
||||
|
@ -182,7 +182,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
|
|||
}
|
||||
free(path);
|
||||
|
||||
path = get_xdg_xcompose_file_path();
|
||||
path = get_xdg_xcompose_file_path(ctx);
|
||||
if (path) {
|
||||
file = fopen(path, "rb");
|
||||
if (file)
|
||||
|
@ -190,7 +190,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
|
|||
}
|
||||
free(path);
|
||||
|
||||
path = get_home_xcompose_file_path();
|
||||
path = get_home_xcompose_file_path(ctx);
|
||||
if (path) {
|
||||
file = fopen(path, "rb");
|
||||
if (file)
|
||||
|
@ -198,7 +198,7 @@ xkb_compose_table_new_from_locale(struct xkb_context *ctx,
|
|||
}
|
||||
free(path);
|
||||
|
||||
path = get_locale_compose_file_path(table->locale);
|
||||
path = get_locale_compose_file_path(ctx, table->locale);
|
||||
if (path) {
|
||||
file = fopen(path, "rb");
|
||||
if (file)
|
||||
|
|
|
@ -34,6 +34,16 @@
|
|||
#include "utils.h"
|
||||
#include "context.h"
|
||||
|
||||
char *
|
||||
xkb_context_getenv(struct xkb_context *ctx, const char *name)
|
||||
{
|
||||
if (ctx->use_secure_getenv) {
|
||||
return secure_getenv(name);
|
||||
} else {
|
||||
return getenv(name);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
xkb_context_num_failed_include_paths(struct xkb_context *ctx)
|
||||
{
|
||||
|
@ -105,7 +115,7 @@ xkb_context_get_default_rules(struct xkb_context *ctx)
|
|||
const char *env = NULL;
|
||||
|
||||
if (ctx->use_environment_names)
|
||||
env = secure_getenv("XKB_DEFAULT_RULES");
|
||||
env = xkb_context_getenv(ctx, "XKB_DEFAULT_RULES");
|
||||
|
||||
return env ? env : DEFAULT_XKB_RULES;
|
||||
}
|
||||
|
@ -116,7 +126,7 @@ xkb_context_get_default_model(struct xkb_context *ctx)
|
|||
const char *env = NULL;
|
||||
|
||||
if (ctx->use_environment_names)
|
||||
env = secure_getenv("XKB_DEFAULT_MODEL");
|
||||
env = xkb_context_getenv(ctx, "XKB_DEFAULT_MODEL");
|
||||
|
||||
return env ? env : DEFAULT_XKB_MODEL;
|
||||
}
|
||||
|
@ -127,7 +137,7 @@ xkb_context_get_default_layout(struct xkb_context *ctx)
|
|||
const char *env = NULL;
|
||||
|
||||
if (ctx->use_environment_names)
|
||||
env = secure_getenv("XKB_DEFAULT_LAYOUT");
|
||||
env = xkb_context_getenv(ctx, "XKB_DEFAULT_LAYOUT");
|
||||
|
||||
return env ? env : DEFAULT_XKB_LAYOUT;
|
||||
}
|
||||
|
@ -136,12 +146,12 @@ static const char *
|
|||
xkb_context_get_default_variant(struct xkb_context *ctx)
|
||||
{
|
||||
const char *env = NULL;
|
||||
const char *layout = secure_getenv("XKB_DEFAULT_LAYOUT");
|
||||
const char *layout = xkb_context_getenv(ctx, "XKB_DEFAULT_LAYOUT");
|
||||
|
||||
/* We don't want to inherit the variant if they haven't also set a
|
||||
* layout, since they're so closely paired. */
|
||||
if (layout && ctx->use_environment_names)
|
||||
env = secure_getenv("XKB_DEFAULT_VARIANT");
|
||||
env = xkb_context_getenv(ctx, "XKB_DEFAULT_VARIANT");
|
||||
|
||||
return env ? env : DEFAULT_XKB_VARIANT;
|
||||
}
|
||||
|
@ -152,7 +162,7 @@ xkb_context_get_default_options(struct xkb_context *ctx)
|
|||
const char *env = NULL;
|
||||
|
||||
if (ctx->use_environment_names)
|
||||
env = secure_getenv("XKB_DEFAULT_OPTIONS");
|
||||
env = xkb_context_getenv(ctx, "XKB_DEFAULT_OPTIONS");
|
||||
|
||||
return env ? env : DEFAULT_XKB_OPTIONS;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "utils.h"
|
||||
#include "context.h"
|
||||
|
||||
|
||||
/**
|
||||
* Append one directory to the context's include path.
|
||||
*/
|
||||
|
@ -77,14 +78,14 @@ err:
|
|||
const char *
|
||||
xkb_context_include_path_get_extra_path(struct xkb_context *ctx)
|
||||
{
|
||||
const char *extra = secure_getenv("XKB_CONFIG_EXTRA_PATH");
|
||||
const char *extra = xkb_context_getenv(ctx, "XKB_CONFIG_EXTRA_PATH");
|
||||
return extra ? extra : DFLT_XKB_CONFIG_EXTRA_PATH;
|
||||
}
|
||||
|
||||
const char *
|
||||
xkb_context_include_path_get_system_path(struct xkb_context *ctx)
|
||||
{
|
||||
const char *root = secure_getenv("XKB_CONFIG_ROOT");
|
||||
const char *root = xkb_context_getenv(ctx, "XKB_CONFIG_ROOT");
|
||||
return root ? root : DFLT_XKB_CONFIG_ROOT;
|
||||
}
|
||||
|
||||
|
@ -98,9 +99,9 @@ xkb_context_include_path_append_default(struct xkb_context *ctx)
|
|||
char *user_path;
|
||||
int ret = 0;
|
||||
|
||||
home = secure_getenv("HOME");
|
||||
home = xkb_context_getenv(ctx, "HOME");
|
||||
|
||||
xdg = secure_getenv("XDG_CONFIG_HOME");
|
||||
xdg = xkb_context_getenv(ctx, "XDG_CONFIG_HOME");
|
||||
if (xdg != NULL) {
|
||||
user_path = asprintf_safe("%s/xkb", xdg);
|
||||
if (user_path) {
|
||||
|
@ -289,13 +290,15 @@ xkb_context_new(enum xkb_context_flags flags)
|
|||
ctx->log_fn = default_log_fn;
|
||||
ctx->log_level = XKB_LOG_LEVEL_ERROR;
|
||||
ctx->log_verbosity = 0;
|
||||
ctx->use_environment_names = !(flags & XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
|
||||
ctx->use_secure_getenv = !(flags & XKB_CONTEXT_NO_SECURE_GETENV);
|
||||
|
||||
/* Environment overwrites defaults. */
|
||||
env = secure_getenv("XKB_LOG_LEVEL");
|
||||
env = xkb_context_getenv(ctx, "XKB_LOG_LEVEL");
|
||||
if (env)
|
||||
xkb_context_set_log_level(ctx, log_level(env));
|
||||
|
||||
env = secure_getenv("XKB_LOG_VERBOSITY");
|
||||
env = xkb_context_getenv(ctx, "XKB_LOG_VERBOSITY");
|
||||
if (env)
|
||||
xkb_context_set_log_verbosity(ctx, log_verbosity(env));
|
||||
|
||||
|
@ -307,8 +310,6 @@ xkb_context_new(enum xkb_context_flags flags)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
ctx->use_environment_names = !(flags & XKB_CONTEXT_NO_ENVIRONMENT_NAMES);
|
||||
|
||||
ctx->atom_table = atom_table_new();
|
||||
if (!ctx->atom_table) {
|
||||
xkb_context_unref(ctx);
|
||||
|
|
|
@ -53,8 +53,12 @@ struct xkb_context {
|
|||
size_t text_next;
|
||||
|
||||
unsigned int use_environment_names : 1;
|
||||
unsigned int use_secure_getenv : 1;
|
||||
};
|
||||
|
||||
char *
|
||||
xkb_context_getenv(struct xkb_context *ctx, const char *name);
|
||||
|
||||
unsigned int
|
||||
xkb_context_num_failed_include_paths(struct xkb_context *ctx);
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ struct rxkb_context {
|
|||
enum context_state context_state;
|
||||
|
||||
bool load_extra_rules_files;
|
||||
bool use_secure_getenv;
|
||||
|
||||
struct list models; /* list of struct rxkb_models */
|
||||
struct list layouts; /* list of struct rxkb_layouts */
|
||||
|
@ -437,6 +438,17 @@ DECLARE_REF_UNREF_FOR_TYPE(rxkb_context);
|
|||
DECLARE_CREATE_FOR_TYPE(rxkb_context);
|
||||
DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_context, log_level, enum rxkb_log_level);
|
||||
|
||||
static char *
|
||||
rxkb_context_getenv(struct rxkb_context *ctx, const char *name)
|
||||
{
|
||||
if (ctx->use_secure_getenv) {
|
||||
return secure_getenv(name);
|
||||
} else {
|
||||
return getenv(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XKB_EXPORT void
|
||||
rxkb_context_set_log_level(struct rxkb_context *ctx,
|
||||
enum rxkb_log_level level)
|
||||
|
@ -508,11 +520,12 @@ rxkb_context_new(enum rxkb_context_flags flags)
|
|||
|
||||
ctx->context_state = CONTEXT_NEW;
|
||||
ctx->load_extra_rules_files = flags & RXKB_CONTEXT_LOAD_EXOTIC_RULES;
|
||||
ctx->use_secure_getenv = !(flags & RXKB_CONTEXT_NO_SECURE_GETENV);
|
||||
ctx->log_fn = default_log_fn;
|
||||
ctx->log_level = RXKB_LOG_LEVEL_ERROR;
|
||||
|
||||
/* Environment overwrites defaults. */
|
||||
env = secure_getenv("RXKB_LOG_LEVEL");
|
||||
env = rxkb_context_getenv(ctx, "RXKB_LOG_LEVEL");
|
||||
if (env)
|
||||
rxkb_context_set_log_level(ctx, log_level(env));
|
||||
|
||||
|
@ -593,9 +606,9 @@ rxkb_context_include_path_append_default(struct rxkb_context *ctx)
|
|||
return false;
|
||||
}
|
||||
|
||||
home = secure_getenv("HOME");
|
||||
home = rxkb_context_getenv(ctx, "HOME");
|
||||
|
||||
xdg = secure_getenv("XDG_CONFIG_HOME");
|
||||
xdg = rxkb_context_getenv(ctx, "XDG_CONFIG_HOME");
|
||||
if (xdg != NULL) {
|
||||
user_path = asprintf_safe("%s/xkb", xdg);
|
||||
if (user_path) {
|
||||
|
@ -619,13 +632,13 @@ rxkb_context_include_path_append_default(struct rxkb_context *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
extra = secure_getenv("XKB_CONFIG_EXTRA_PATH");
|
||||
extra = rxkb_context_getenv(ctx, "XKB_CONFIG_EXTRA_PATH");
|
||||
if (extra != NULL)
|
||||
ret |= rxkb_context_include_path_append(ctx, extra);
|
||||
else
|
||||
ret |= rxkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_EXTRA_PATH);
|
||||
|
||||
root = secure_getenv("XKB_CONFIG_ROOT");
|
||||
root = rxkb_context_getenv(ctx, "XKB_CONFIG_ROOT");
|
||||
if (root != NULL)
|
||||
ret |= rxkb_context_include_path_append(ctx, root);
|
||||
else
|
||||
|
|
|
@ -382,7 +382,7 @@ matcher_include(struct matcher *m, struct scanner *parent_scanner,
|
|||
scanner_buf_append(&s, '%');
|
||||
}
|
||||
else if (scanner_chr(&s, 'H')) {
|
||||
const char *home = secure_getenv("HOME");
|
||||
const char *home = xkb_context_getenv(m->ctx, "HOME");
|
||||
if (!home) {
|
||||
scanner_err(&s, "%%H was used in an include statement, but the HOME environment variable is not set");
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue