1 /**
2  * xrdp: A Remote Desktop Protocol server.
3  *
4  * Copyright (C) Jay Sorg 2004-2014
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #ifndef LOG_H
20 #define LOG_H
21 
22 #include <pthread.h>
23 
24 #include "arch.h"
25 #include "defines.h"
26 #include "list.h"
27 
28 /* logging buffer size */
29 #define LOG_BUFFER_SIZE      8192
30 #define LOGGER_NAME_SIZE     50
31 
32 /* logging levels */
33 enum logLevels
34 {
35     LOG_LEVEL_ALWAYS = 0,
36     LOG_LEVEL_ERROR,     /* for describing non-recoverable error states in a request or method */
37     LOG_LEVEL_WARNING,   /* for describing recoverable error states in a request or method */
38     LOG_LEVEL_INFO,      /* for low verbosity and high level descriptions of normal operations */
39     LOG_LEVEL_DEBUG,     /* for medium verbosity and low level descriptions of normal operations */
40     LOG_LEVEL_TRACE,     /* for high verbosity and low level descriptions of normal operations (eg. method or wire tracing) */
41     LOG_LEVEL_NEVER,
42 };
43 
44 /* startup return values */
45 enum logReturns
46 {
47     LOG_STARTUP_OK = 0,
48     LOG_ERROR_MALLOC,
49     LOG_ERROR_NULL_FILE,
50     LOG_ERROR_FILE_OPEN,
51     LOG_ERROR_NO_CFG,
52     LOG_ERROR_FILE_NOT_OPEN,
53     LOG_GENERAL_ERROR
54 };
55 
56 #define SESMAN_CFG_LOGGING            "Logging"
57 #define SESMAN_CFG_LOGGING_LOGGER     "LoggingPerLogger"
58 #define SESMAN_CFG_LOG_FILE           "LogFile"
59 #define SESMAN_CFG_LOG_LEVEL          "LogLevel"
60 #define SESMAN_CFG_LOG_ENABLE_CONSOLE "EnableConsole"
61 #define SESMAN_CFG_LOG_CONSOLE_LEVEL  "ConsoleLevel"
62 #define SESMAN_CFG_LOG_ENABLE_SYSLOG  "EnableSyslog"
63 #define SESMAN_CFG_LOG_SYSLOG_LEVEL   "SyslogLevel"
64 #define SESMAN_CFG_LOG_ENABLE_PID     "EnableProcessId"
65 
66 /* enable threading */
67 /*#define LOG_ENABLE_THREAD*/
68 
69 #ifdef XRDP_DEBUG
70 
71 #define LOG_PER_LOGGER_LEVEL
72 
73 /**
74  * @brief Logging macro for messages that are for an XRDP developer to
75  * understand and debug XRDP code.
76  *
77  * Note: all log levels are relavant to help a developer understand XRDP at
78  *      different levels of granularity.
79  *
80  * Note: the logging function calls are removed when XRDP_DEBUG is NOT defined.
81  *
82  * Note: when the build is configured with --enable-xrdpdebug, then
83  *      the log level can be configured per the source file name or method name
84  *      (with the suffix "()") in the [LoggingPerLogger]
85  *      section of the configuration file.
86  *
87  *      For example:
88  *      ```
89  *      [LoggingPerLogger]
90  *      xrdp.c=DEBUG
91  *      main()=WARNING
92  *      ```
93  *
94  * @param lvl, the log level
95  * @param msg, the log text as a printf format c-string
96  * @param ... the arguments for the printf format c-string
97  */
98 #define LOG_DEVEL(log_level, args...) \
99     log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
100 
101 /**
102  * @brief Logging macro for messages that are for a systeam administrator to
103  * configure and run XRDP on their machine.
104  *
105  * Note: the logging function calls contain additional code location info when
106  *      XRDP_DEBUG is defined.
107  *
108  * @param lvl, the log level
109  * @param msg, the log text as a printf format c-string
110  * @param ... the arguments for the printf format c-string
111  */
112 #define LOG(log_level, args...) \
113     log_message_with_location(__func__, __FILE__, __LINE__, log_level, args)
114 
115 /**
116  * @brief Logging macro for logging the contents of a byte array using a hex
117  * dump format.
118  *
119  * Note: the logging function calls are removed when XRDP_DEBUG is NOT defined.
120  *
121  * @param log_level, the log level
122  * @param message, a message prefix for the hex dump. Note: no printf like
123  *          formatting is done to this message.
124  * @param buffer, a pointer to the byte array to log as a hex dump
125  * @param length, the length of the byte array to log
126  */
127 #define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length)  \
128     log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
129 
130 /**
131  * @brief Logging macro for logging the contents of a byte array using a hex
132  * dump format.
133  *
134  * @param log_level, the log level
135  * @param message, a message prefix for the hex dump. Note: no printf like
136  *          formatting is done to this message.
137  * @param buffer, a pointer to the byte array to log as a hex dump
138  * @param length, the length of the byte array to log
139  */
140 #define LOG_HEXDUMP(log_level, message, buffer, length)  \
141     log_hexdump_with_location(__func__, __FILE__, __LINE__, log_level, message, buffer, length)
142 
143 #else
144 #define LOG(log_level, args...) log_message(log_level, args)
145 #define LOG_HEXDUMP(log_level, message, buffer, length)  \
146     log_hexdump(log_level, message, buffer, length)
147 
148 /* Since log_message() returns a value ensure that the elided versions of
149  * LOG_DEVEL and LOG_DEVEL_HEXDUMP also "fake" returning the success value
150  */
151 #define LOG_DEVEL(log_level, args...) UNUSED_VAR(LOG_STARTUP_OK)
152 #define LOG_DEVEL_HEXDUMP(log_level, message, buffer, length) UNUSED_VAR(LOG_STARTUP_OK)
153 
154 #endif
155 
156 enum log_logger_type
157 {
158     LOG_TYPE_FILE = 0,
159     LOG_TYPE_FUNCTION,
160 };
161 
162 struct log_logger_level
163 {
164     enum logLevels log_level;
165     enum log_logger_type logger_type;
166     char logger_name[LOGGER_NAME_SIZE + 1];
167 };
168 
169 struct log_config
170 {
171     const char *program_name;
172     char *log_file;
173     int fd;
174     enum logLevels log_level;
175     int enable_console;
176     enum logLevels console_level;
177     int enable_syslog;
178     enum logLevels syslog_level;
179     struct list *per_logger_level;
180     int dump_on_start;
181     int enable_pid;
182     pthread_mutex_t log_lock;
183     pthread_mutexattr_t log_lock_attr;
184 };
185 
186 /* internal functions, only used in log.c if this ifdef is defined.*/
187 #ifdef LOGINTERNALSTUFF
188 
189 /**
190  *
191  * @brief Starts the logging subsystem
192  * @param l_cfg logging system configuration
193  * @return
194  *
195  */
196 enum logReturns
197 internal_log_start(struct log_config *l_cfg);
198 
199 /**
200  *
201  * @brief Shuts down the logging subsystem
202  * @param l_cfg pointer to the logging subsystem to stop
203  *
204  */
205 enum logReturns
206 internal_log_end(struct log_config *l_cfg);
207 
208 /**
209  * Converts a log level to a string
210  * @param lvl, the loglevel
211  * @param str pointer where the string will be stored.
212  */
213 void
214 internal_log_lvl2str(const enum logLevels lvl, char *str);
215 
216 /**
217  *
218  * @brief Converts a string to a log level
219  * @param s The string to convert
220  * @return The corresponding level or LOG_LEVEL_DEBUG if error
221  *
222  */
223 enum logLevels
224 internal_log_text2level(const char *buf);
225 
226 /**
227  * A function that init our struct that holds all state and
228  * also init its content.
229  * @return  LOG_STARTUP_OK or LOG_ERROR_MALLOC
230  */
231 struct log_config *
232 internalInitAndAllocStruct(void);
233 
234 /**
235  * Print the contents of the logging config to stdout.
236  */
237 void
238 internal_log_config_dump(struct log_config *config);
239 
240 /**
241  * the log function that all files use to log an event.
242  * @param lvl, the loglevel
243  * @param override_destination_level, if true then the destination log level is not used
244  * @param override_log_level, the loglevel instead of the destination log level if override_destination_level is true
245  * @param msg, the logtext.
246  * @param ap, the values for the message format arguments
247  * @return
248  */
249 enum logReturns
250 internal_log_message(const enum logLevels lvl,
251                      const bool_t override_destination_level,
252                      const enum logLevels override_log_level,
253                      const char *msg,
254                      va_list ap);
255 
256 /**
257  * @param log_level, the log level
258  * @param override_destination_level, if true then the destination log level is ignored.
259  * @param override_log_level, the log level to use instead of the destination log level
260  *      if override_destination_level is true
261  * @return true if at least one log destination will accept a message logged at the given level.
262  */
263 bool_t
264 internal_log_is_enabled_for_level(const enum logLevels log_level,
265                                   const bool_t override_destination_level,
266                                   const enum logLevels override_log_level);
267 
268 /**
269  * @param function_name, the function name (typicaly the __func__ macro)
270  * @param file_name, the file name (typicaly the __FILE__ macro)
271  * @param[out] log_level_return, the log level to use instead of the destination log level
272  * @return true if the logger location overrides the destination log levels
273  */
274 bool_t
275 internal_log_location_overrides_level(const char *function_name,
276                                       const char *file_name,
277                                       enum logLevels *log_level_return);
278 
279 /*End of internal functions*/
280 #endif
281 
282 /**
283  * This function initialize the log facilities according to the configuration
284  * file, that is described by the in parameter.
285  * @param iniFile
286  * @param applicationName the name that is used in the log for the running
287  *                        application
288  * @param dump_on_start Whether to dump the config on stdout before
289  *                      logging is started
290  * @return LOG_STARTUP_OK on success
291  */
292 enum logReturns
293 log_start(const char *iniFile, const char *applicationName,
294           bool_t dump_on_start);
295 
296 /**
297  * An alternative log_start where the caller gives the params directly.
298  * @param config
299  * @return
300  *
301  * @post to avoid memory leaks, the config argument must be free'ed using
302  * `log_config_free()`
303  */
304 enum logReturns
305 log_start_from_param(const struct log_config *src_log_config);
306 
307 /**
308  * Sets up a suitable log config for writing to the console only
309  * (i.e. for a utility)
310  *
311  * The config can be customised by the caller before calling
312  * log_start_from_param()
313  *
314  * @param Default log level
315  * @param Log level name, or NULL. This can be used to provide an
316  *        override to the default log level, by environment variable or
317  *        argument.
318  *
319  * @return pointer to struct log_config.
320  */
321 struct log_config *
322 log_config_init_for_console(enum logLevels lvl, const char *override_name);
323 
324 /**
325  * Read configuration from a file and store the values in the returned
326  * log_config.
327  * @param file
328  * @param applicationName, the application name used in the log events.
329  * @param section_prefix, prefix for the logging sections to parse
330  * @return
331  */
332 struct log_config *
333 log_config_init_from_config(const char *iniFilename,
334                             const char *applicationName,
335                             const char *section_prefix);
336 
337 /**
338  * Free the memory for the log_config struct.
339  */
340 enum logReturns
341 log_config_free(struct log_config *config);
342 
343 /**
344  * Function that terminates all logging
345  * @return
346  */
347 enum logReturns
348 log_end(void);
349 
350 /**
351  * the log function that all files use to log an event.
352  *
353  * Please prefer to use the LOG and LOG_DEVEL macros instead of this function directly.
354  *
355  * @param lvl, the loglevel
356  * @param msg, the logtext.
357  * @param ...
358  * @return
359  */
360 enum logReturns
361 log_message(const enum logLevels lvl, const char *msg, ...) printflike(2, 3);
362 
363 enum logReturns
364 log_hexdump(const enum logLevels log_level,
365             const char *msg,
366             const char *p,
367             int len);
368 
369 /**
370  * the log function that all files use to log an event,
371  * with the function name and file line.
372  *
373  * Please prefer to use the LOG and LOG_DEVEL macros instead of this function directly.
374  *
375  * @param function_name, the function name (typicaly the __func__ macro)
376  * @param file_name, the file name (typicaly the __FILE__ macro)
377  * @param line_number, the line number in the file (typicaly the __LINE__ macro)
378  * @param lvl, the loglevel
379  * @param msg, the logtext.
380  * @param ...
381  * @return
382  */
383 enum logReturns
384 log_message_with_location(const char *function_name,
385                           const char *file_name,
386                           const int line_number,
387                           const enum logLevels lvl,
388                           const char *msg,
389                           ...) printflike(5, 6);
390 
391 enum logReturns
392 log_hexdump_with_location(const char *function_name,
393                           const char *file_name,
394                           const int line_number,
395                           const enum logLevels log_level,
396                           const char *msg,
397                           const char *p,
398                           int len);
399 
400 /**
401  * This function returns the configured file name for the logfile
402  * @param replybuf the buffer where the reply is stored
403  * @param bufsize how big is the reply buffer.
404  * @return
405  */
406 char *getLogFile(char *replybuf, int bufsize);
407 #endif
408