/src/sudo/plugins/sudoers/locale.c
Line | Count | Source |
1 | | /* |
2 | | * SPDX-License-Identifier: ISC |
3 | | * |
4 | | * Copyright (c) 2012-2016, 2020, 2022 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 | | #include <config.h> |
20 | | |
21 | | #include <stdio.h> |
22 | | #include <stdlib.h> |
23 | | #include <string.h> |
24 | | #ifdef HAVE_STDBOOL_H |
25 | | # include <stdbool.h> |
26 | | #else |
27 | | # include <compat/stdbool.h> |
28 | | #endif /* HAVE_STDBOOL_H */ |
29 | | |
30 | | #define DEFAULT_TEXT_DOMAIN "sudoers" |
31 | | |
32 | | #include <sudo_compat.h> |
33 | | #include <sudo_eventlog.h> |
34 | | #include <sudo_fatal.h> |
35 | | #include <sudo_gettext.h> |
36 | | #include <sudoers_debug.h> |
37 | | |
38 | | #include <defaults.h> |
39 | | #include <logging.h> |
40 | | |
41 | | static int current_locale = SUDOERS_LOCALE_USER; |
42 | | static char *user_locale; |
43 | | static char *sudoers_locale; |
44 | | |
45 | | int |
46 | | sudoers_getlocale(void) |
47 | 0 | { |
48 | 0 | debug_decl(sudoers_getlocale, SUDOERS_DEBUG_UTIL); |
49 | 0 | debug_return_int(current_locale); |
50 | 0 | } |
51 | | |
52 | | bool |
53 | | sudoers_initlocale(const char *ulocale, const char *slocale) |
54 | 15 | { |
55 | 15 | debug_decl(sudoers_initlocale, SUDOERS_DEBUG_UTIL); |
56 | | |
57 | 15 | if (ulocale != NULL) { |
58 | 8 | free(user_locale); |
59 | 8 | if ((user_locale = strdup(ulocale)) == NULL) |
60 | 0 | debug_return_bool(false); |
61 | 8 | } |
62 | 15 | if (slocale != NULL) { |
63 | 15 | free(sudoers_locale); |
64 | 15 | if ((sudoers_locale = strdup(slocale)) == NULL) |
65 | 0 | debug_return_bool(false); |
66 | 15 | } |
67 | 15 | sudo_debug_printf(SUDO_DEBUG_INFO, "%s: user locale %s, sudoers locale %s", |
68 | 15 | __func__, user_locale, sudoers_locale); |
69 | 15 | debug_return_bool(true); |
70 | 15 | } |
71 | | |
72 | | /* |
73 | | * Set locale to user or sudoers value. |
74 | | * Returns true on success and false on failure, |
75 | | * If prev_locale is non-NULL it will be filled in with the |
76 | | * old SUDOERS_LOCALE_* value. |
77 | | */ |
78 | | bool |
79 | | sudoers_setlocale(int locale_type, int *prev_locale) |
80 | 43.9k | { |
81 | 43.9k | char *res = NULL; |
82 | 43.9k | debug_decl(sudoers_setlocale, SUDOERS_DEBUG_UTIL); |
83 | | |
84 | 43.9k | switch (locale_type) { |
85 | 21.9k | case SUDOERS_LOCALE_USER: |
86 | 21.9k | if (prev_locale) |
87 | 21.9k | *prev_locale = current_locale; |
88 | 21.9k | if (current_locale != SUDOERS_LOCALE_USER) { |
89 | 21.9k | current_locale = SUDOERS_LOCALE_USER; |
90 | 21.9k | sudo_debug_printf(SUDO_DEBUG_DEBUG, |
91 | 21.9k | "%s: setting locale to %s (user)", __func__, |
92 | 21.9k | user_locale ? user_locale : ""); |
93 | 21.9k | res = setlocale(LC_ALL, user_locale ? user_locale : ""); |
94 | 21.9k | if (res != NULL && user_locale == NULL) { |
95 | 0 | user_locale = setlocale(LC_ALL, NULL); |
96 | 0 | if (user_locale != NULL) |
97 | 0 | user_locale = strdup(user_locale); |
98 | 0 | if (user_locale == NULL) |
99 | 0 | res = NULL; |
100 | 0 | } |
101 | 21.9k | } |
102 | 21.9k | break; |
103 | 21.9k | case SUDOERS_LOCALE_SUDOERS: |
104 | 21.9k | if (prev_locale) |
105 | 0 | *prev_locale = current_locale; |
106 | 21.9k | if (current_locale != SUDOERS_LOCALE_SUDOERS) { |
107 | 21.9k | current_locale = SUDOERS_LOCALE_SUDOERS; |
108 | 21.9k | sudo_debug_printf(SUDO_DEBUG_DEBUG, |
109 | 21.9k | "%s: setting locale to %s (sudoers)", __func__, |
110 | 21.9k | sudoers_locale ? sudoers_locale : "C"); |
111 | 21.9k | res = setlocale(LC_ALL, sudoers_locale ? sudoers_locale : "C"); |
112 | 21.9k | if (res == NULL && sudoers_locale != NULL) { |
113 | 0 | if (strcmp(sudoers_locale, "C") != 0) { |
114 | 0 | free(sudoers_locale); |
115 | 0 | sudoers_locale = strdup("C"); |
116 | 0 | if (sudoers_locale != NULL) |
117 | 0 | res = setlocale(LC_ALL, "C"); |
118 | 0 | } |
119 | 0 | } |
120 | 21.9k | } |
121 | 21.9k | break; |
122 | 43.9k | } |
123 | 43.9k | debug_return_bool(res ? true : false); |
124 | 43.9k | } |
125 | | |
126 | | bool |
127 | | sudoers_warn_setlocale(bool restore, int *cookie) |
128 | 24 | { |
129 | 24 | debug_decl(sudoers_warn_setlocale, SUDOERS_DEBUG_UTIL); |
130 | | |
131 | 24 | if (restore) |
132 | 12 | debug_return_bool(sudoers_setlocale(*cookie, NULL)); |
133 | 12 | debug_return_bool(sudoers_setlocale(SUDOERS_LOCALE_USER, cookie)); |
134 | 12 | } |
135 | | |
136 | | /* |
137 | | * Callback for sudoers_locale sudoers setting. |
138 | | */ |
139 | | bool |
140 | | sudoers_locale_callback(struct sudoers_context *ctx, const char *file, |
141 | | int line, int column, const union sudo_defs_val *sd_un, int op) |
142 | 0 | { |
143 | 0 | debug_decl(sudoers_locale_callback, SUDOERS_DEBUG_UTIL); |
144 | |
|
145 | 0 | if (sudoers_initlocale(NULL, sd_un->str)) { |
146 | 0 | if (setlocale(LC_ALL, sd_un->str) != NULL) |
147 | 0 | debug_return_bool(true); |
148 | 0 | } |
149 | 0 | debug_return_bool(false); |
150 | 0 | } |