1 /**
2 * xrdp: A Remote Desktop Protocol server.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * This file implements the interface in chansrv_config.h
17 */
18 #if defined(HAVE_CONFIG_H)
19 #include <config_ac.h>
20 #endif
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25
26 #include "arch.h"
27
28 #include "list.h"
29 #include "log.h"
30 #include "file.h"
31 #include "os_calls.h"
32
33 #include "chansrv_config.h"
34 #include "string_calls.h"
35
36 /* Default settings */
37 #define DEFAULT_USE_UNIX_SOCKET 0
38 #define DEFAULT_RESTRICT_OUTBOUND_CLIPBOARD 0
39 #define DEFAULT_ENABLE_FUSE_MOUNT 1
40 #define DEFAULT_FUSE_MOUNT_NAME "xrdp-client"
41 #define DEFAULT_FILE_UMASK 077
42
43 /**
44 * Type used for passing a logging function about
45 */
46 typedef
47 printflike(2, 3)
48 enum logReturns (*log_func_t)(const enum logLevels lvl,
49 const char *msg, ...);
50
51 /***************************************************************************//**
52 * @brief Error logging function to use to log to stdout
53 *
54 * Has the same signature as the log_message() function
55 */
56 static enum logReturns
log_to_stdout(const enum logLevels lvl,const char * msg,...)57 log_to_stdout(const enum logLevels lvl, const char *msg, ...)
58 {
59 char buff[256];
60 va_list ap;
61
62 va_start(ap, msg);
63 vsnprintf(buff, sizeof(buff), msg, ap);
64 va_end(ap);
65 g_writeln("%s", buff);
66
67 return LOG_STARTUP_OK;
68 }
69
70 /***************************************************************************//**
71 * Reads the config values we need from the [Globals] section
72 *
73 * @param logmsg Function to use to log messages
74 * @param names List of definitions in the section
75 * @params values List of corresponding values for the names
76 * @params cfg Pointer to structure we're filling in
77 *
78 * @return 0 for success
79 */
80 static int
read_config_globals(log_func_t logmsg,struct list * names,struct list * values,struct config_chansrv * cfg)81 read_config_globals(log_func_t logmsg,
82 struct list *names, struct list *values,
83 struct config_chansrv *cfg)
84 {
85 int error = 0;
86 int index;
87
88 for (index = 0; index < names->count; ++index)
89 {
90 const char *name = (const char *)list_get_item(names, index);
91 const char *value = (const char *)list_get_item(values, index);
92
93 if (g_strcasecmp(name, "ListenAddress") == 0)
94 {
95 if (g_strcasecmp(value, "127.0.0.1") == 0)
96 {
97 cfg->use_unix_socket = 1;
98 }
99 }
100 }
101
102 return error;
103 }
104
105 /***************************************************************************//**
106 * Reads the config values we need from the [Security] section
107 *
108 * @param logmsg Function to use to log messages
109 * @param names List of definitions in the section
110 * @params values List of corresponding values for the names
111 * @params cfg Pointer to structure we're filling in
112 *
113 * @return 0 for success
114 */
115 static int
read_config_security(log_func_t logmsg,struct list * names,struct list * values,struct config_chansrv * cfg)116 read_config_security(log_func_t logmsg,
117 struct list *names, struct list *values,
118 struct config_chansrv *cfg)
119 {
120 int error = 0;
121 int index;
122
123 for (index = 0; index < names->count; ++index)
124 {
125 const char *name = (const char *)list_get_item(names, index);
126 const char *value = (const char *)list_get_item(values, index);
127
128 if (g_strcasecmp(name, "RestrictOutboundClipboard") == 0)
129 {
130 cfg->restrict_outbound_clipboard = g_text2bool(value);
131 }
132 }
133
134 return error;
135 }
136
137 /***************************************************************************//**
138 * Reads the config values we need from the [Chansrv] section
139 *
140 * @param logmsg Function to use to log messages
141 * @param names List of definitions in the section
142 * @params values List of corresponding values for the names
143 * @params cfg Pointer to structure we're filling in
144 *
145 * @return 0 for success
146 */
147 static int
read_config_chansrv(log_func_t logmsg,struct list * names,struct list * values,struct config_chansrv * cfg)148 read_config_chansrv(log_func_t logmsg,
149 struct list *names, struct list *values,
150 struct config_chansrv *cfg)
151 {
152 int error = 0;
153 int index;
154
155 for (index = 0; index < names->count; ++index)
156 {
157 const char *name = (const char *)list_get_item(names, index);
158 const char *value = (const char *)list_get_item(values, index);
159
160 if (g_strcasecmp(name, "EnableFuseMount") == 0)
161 {
162 cfg->enable_fuse_mount = g_text2bool(value);
163 }
164 if (g_strcasecmp(name, "FuseMountName") == 0)
165 {
166 g_free(cfg->fuse_mount_name);
167 cfg->fuse_mount_name = g_strdup(value);
168 if (cfg->fuse_mount_name == NULL)
169 {
170 logmsg(LOG_LEVEL_ERROR, "Can't alloc FuseMountName");
171 error = 1;
172 break;
173 }
174 }
175 else if (g_strcasecmp(name, "FileUmask") == 0)
176 {
177 cfg->file_umask = strtol(value, NULL, 0);
178 }
179 }
180
181 return error;
182 }
183
184 /***************************************************************************//**
185 * @brief returns a config block with default values
186 *
187 * @return Block, or NULL for no memory
188 */
189 static struct config_chansrv *
new_config(void)190 new_config(void)
191 {
192 /* Do all the allocations at the beginning, then check them together */
193 struct config_chansrv *cfg = g_new0(struct config_chansrv, 1);
194 char *fuse_mount_name = g_strdup(DEFAULT_FUSE_MOUNT_NAME);
195 if (cfg == NULL || fuse_mount_name == NULL)
196 {
197 /* At least one memory allocation failed */
198 g_free(fuse_mount_name);
199 g_free(cfg);
200 cfg = NULL;
201 }
202 else
203 {
204 cfg->use_unix_socket = DEFAULT_USE_UNIX_SOCKET;
205 cfg->enable_fuse_mount = DEFAULT_ENABLE_FUSE_MOUNT;
206 cfg->restrict_outbound_clipboard = DEFAULT_RESTRICT_OUTBOUND_CLIPBOARD;
207 cfg->fuse_mount_name = fuse_mount_name;
208 cfg->file_umask = DEFAULT_FILE_UMASK;
209 }
210
211 return cfg;
212 }
213
214 /******************************************************************************/
215 struct config_chansrv *
config_read(int use_logger,const char * sesman_ini)216 config_read(int use_logger, const char *sesman_ini)
217 {
218 int error = 0;
219 struct config_chansrv *cfg = NULL;
220 log_func_t logmsg = (use_logger) ? log_message : log_to_stdout;
221 int fd;
222
223 fd = g_file_open_ex(sesman_ini, 1, 0, 0, 0);
224 if (fd < 0)
225 {
226 logmsg(LOG_LEVEL_ERROR, "Can't open config file %s", sesman_ini);
227 error = 1;
228 }
229 else
230 {
231 if ((cfg = new_config()) == NULL)
232 {
233 logmsg(LOG_LEVEL_ERROR, "Can't alloc config block");
234 error = 1;
235 }
236 else
237 {
238 struct list *names = list_create();
239 struct list *values = list_create();
240
241 names->auto_free = 1;
242 values->auto_free = 1;
243
244 if (!error && file_read_section(fd, "Globals", names, values) == 0)
245 {
246 error = read_config_globals(logmsg, names, values, cfg);
247 }
248
249
250 if (!error && file_read_section(fd, "Security", names, values) == 0)
251 {
252 error = read_config_security(logmsg, names, values, cfg);
253 }
254
255 if (!error && file_read_section(fd, "Chansrv", names, values) == 0)
256 {
257 error = read_config_chansrv(logmsg, names, values, cfg);
258 }
259
260 list_delete(names);
261 list_delete(values);
262 }
263
264 g_file_close(fd);
265 }
266
267 if (error)
268 {
269 config_free(cfg);
270 cfg = NULL;
271 }
272
273 return cfg;
274 }
275
276 /******************************************************************************/
277 void
config_dump(struct config_chansrv * config)278 config_dump(struct config_chansrv *config)
279 {
280 g_writeln("Global configuration:");
281 g_writeln(" UseUnixSocket (derived): %s",
282 g_bool2text(config->use_unix_socket));
283
284 g_writeln("\nSecurity configuration:");
285 g_writeln(" RestrictOutboundClipboard: %s",
286 g_bool2text(config->restrict_outbound_clipboard));
287
288 g_writeln("\nChansrv configuration:");
289 g_writeln(" EnableFuseMount %s",
290 g_bool2text(config->enable_fuse_mount));
291 g_writeln(" FuseMountName: %s", config->fuse_mount_name);
292 g_writeln(" FileMask: 0%o", config->file_umask);
293 }
294
295 /******************************************************************************/
296 void
config_free(struct config_chansrv * cc)297 config_free(struct config_chansrv *cc)
298 {
299 if (cc != NULL)
300 {
301 g_free(cc->fuse_mount_name);
302 g_free(cc);
303 }
304 }
305