37 if (strlen(*p) >= 3 && !strncmp(*p,
"--", 2))
46 return c ==
'\0' || isspace(c);
50parse_line(
const char *line,
char *p[],
const int n,
const char *file,
const int line_num,
53 const int STATE_INITIAL = 0;
54 const int STATE_READING_QUOTED_PARM = 1;
55 const int STATE_READING_UNQUOTED_PARM = 2;
56 const int STATE_DONE = 3;
57 const int STATE_READING_SQUOTED_PARM = 4;
59 const char *error_prefix =
"";
63 int state = STATE_INITIAL;
64 bool backslash =
false;
68 unsigned int parm_len = 0;
74 error_prefix =
"ERROR: ";
82 if (!backslash && in ==
'\\' && state != STATE_READING_SQUOTED_PARM)
88 if (state == STATE_INITIAL)
92 if (in ==
';' || in ==
'#')
96 if (!backslash && in ==
'\"')
98 state = STATE_READING_QUOTED_PARM;
100 else if (!backslash && in ==
'\'')
102 state = STATE_READING_SQUOTED_PARM;
107 state = STATE_READING_UNQUOTED_PARM;
111 else if (state == STATE_READING_UNQUOTED_PARM)
113 if (!backslash &&
space(in))
122 else if (state == STATE_READING_QUOTED_PARM)
124 if (!backslash && in ==
'\"')
133 else if (state == STATE_READING_SQUOTED_PARM)
144 if (state == STATE_DONE)
148 memcpy(p[ret], parm, parm_len);
149 p[ret][parm_len] =
'\0';
150 state = STATE_INITIAL;
155 if (backslash && out)
157 if (!(out ==
'\\' || out ==
'\"' ||
space(out)))
160 msg(msglevel,
"%sOptions warning: Bad backslash ('\\') usage in %s:%d",
161 error_prefix, file, line_num);
164 "%sOptions warning: Bad backslash ('\\') usage in %s:%d: remember that backslashes are treated as shell-escapes and if you need to pass backslash characters as part of a Windows filename, you should use double backslashes such as \"c:\\\\" PACKAGE
166 error_prefix, file, line_num);
177 if (parm_len >=
SIZE(parm))
179 parm[
SIZE(parm) - 1] = 0;
180 msg(msglevel,
"%sOptions error: Parameter at %s:%d is too long (%d chars max): %s",
181 error_prefix, file, line_num, (
int)
SIZE(parm), parm);
184 parm[parm_len++] = out;
193 }
while (*c++ !=
'\0');
195 if (state == STATE_READING_QUOTED_PARM)
197 msg(msglevel,
"%sOptions error: No closing quotation (\") in %s:%d", error_prefix, file,
201 if (state == STATE_READING_SQUOTED_PARM)
203 msg(msglevel,
"%sOptions error: No closing single quotation (\') in %s:%d", error_prefix,
207 if (state != STATE_INITIAL)
209 msg(msglevel,
"%sOptions error: Residual parse state (%d) in %s:%d", error_prefix, state,
216 for (i = 0; i < ret; ++i)
247 if ((
int)strlen(line) + 1 < size)
266 bool endtagfound =
false;
271 const char *line_ptr = line;
273 while (isspace(*line_ptr))
277 if (!strncmp(line_ptr, close_tag, strlen(close_tag)))
282 if (!
buf_safe(&buf, strlen(line) + 1))
295 msg(
M_FATAL,
"ERROR: Endtag %s missing", close_tag);
307 int num_inline_lines = 0;
312 if (arg[0] ==
'<' && arg[strlen(arg) - 1] ==
'>')
316 arg[strlen(arg) - 1] =
'\0';
325 return num_inline_lines;
348 const int top_line,
const msglvl_t msglevel,
349 const uint64_t permission_mask, uint64_t *option_types_found,
352 const int max_recursive_levels = 10;
358 if (level <= max_recursive_levels)
360 if (
streq(file,
"stdin"))
371 while (fgets(line,
sizeof(line),
fp))
379 "In %s:%d: Maximum option line length (%d) exceeded, line starts with %s",
384 if (line_num == 1 && strncmp(line,
"\xEF\xBB\xBF", 3) == 0)
388 if (
parse_line(line + offset, p,
SIZE(p) - 1, file, line_num, msglevel,
394 permission_mask, option_types_found, es);
395 line_num += lines_inline;
405 msg(msglevel,
"In %s:%d: Error opening configuration file: %s", top_file, top_line,
412 "In %s:%d: Maximum recursive include levels exceeded in include attempt of file %s -- probably you have a configuration file that tries to include itself.",
413 top_file, top_line, file);
421 const msglvl_t msglevel,
const uint64_t permission_mask,
422 uint64_t *option_types_found,
struct env_set *es)
428 buf_set_read(&multiline, (uint8_t *)config, strlen(config));
430 while (
buf_parse(&multiline,
'\n', line,
sizeof(line)))
439 add_option(
options, p, lines_inline, prefix, line_num, 0, msglevel, permission_mask,
440 option_types_found, es);
441 line_num += lines_inline;
450 const uint64_t permission_mask, uint64_t *option_types_found,
struct env_set *es)
459 if (argc == 2 && strncmp(
argv[1],
"--", 2))
465 add_option(
options, p,
false, NULL, 0, 0, msglevel, permission_mask, option_types_found,
471 for (
int i = 1; i < argc; ++i)
476 if (strncmp(p[0],
"--", 2))
479 "I'm trying to parse \"%s\" as an --option parameter but I don't see a leading '--'",
492 char *arg =
argv[i + j];
493 if (strncmp(arg,
"--", 2))
503 add_option(
options, p,
false, NULL, 0, 0, msglevel, permission_mask, option_types_found,
512 uint64_t permission_mask, uint64_t *option_types_found,
513 struct env_set *es,
bool is_update)
517 const char *file =
"[PUSH-OPTIONS]";
520 while (
buf_parse(buf,
',', line,
sizeof(line)))
525 uint64_t push_update_option_flags = 0;
529 while (isspace(line[i]))
556 option_types_found, es);
561 option_types_found, es);
571 option_types_found, es);
580 const uint64_t permission_mask, uint64_t *option_types_found,
583 msg(
D_PUSH,
"OPTIONS IMPORT: reading client specific options from: %s", filename);
584 read_config_file(o, filename, 0, filename, 0, msglevel, permission_mask, option_types_found,
590 const uint64_t permission_mask, uint64_t *option_types_found,
594 option_types_found, es);
void free_buf(struct buffer *buf)
Free the memory allocated for a buffer.
void buf_clear(struct buffer *buf)
Zeroise and reset a buffer.
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Allocate memory and, optionally, zero it.
struct buffer alloc_buf(size_t size)
Allocate a buffer of the given size.
bool buf_parse(struct buffer *buf, const int delim, char *line, const int size)
Extract the next token from a buffer, delimited by a given character.
char * string_alloc(const char *str, struct gc_arena *gc)
Duplicate a string, allocating memory under garbage collection.
#define BSTR(buf)
Return the buffer content pointer cast to char *.
static bool buf_copy(struct buffer *dest, const struct buffer *src)
Copy the content of one buffer to the end of another.
static bool buf_safe(const struct buffer *buf, size_t len)
Check whether len bytes can be appended to a buffer.
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
Initialise a buffer with an externally provided read-only memory region.
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
static SERVICE_STATUS status
void remove_option(struct context *c, struct options *options, char *p[], bool is_inline, const char *file, int line, const msglvl_t msglevel, const uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es)
Resets options found in the PUSH_UPDATE message that are preceded by the - flag.
void update_option(struct context *c, struct options *options, char *p[], bool is_inline, const char *file, int line, const int level, const msglvl_t msglevel, const uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es)
Processes an option to update.
void add_option(struct options *options, char *p[], bool is_inline, const char *file, int line, const int level, const msglvl_t msglevel, const uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es)
static bool in_src_get(const struct in_src *is, char *line, const int size)
void options_server_import(struct options *o, const char *filename, msglvl_t msglevel, const uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es)
static int check_inline_file_via_buf(struct buffer *multiline, char *p[], struct gc_arena *gc)
static int check_inline_file(struct in_src *is, char *p[], struct gc_arena *gc)
static bool space(char c)
static void bypass_doubledash(char **p)
void parse_argv(struct options *options, const int argc, char *argv[], const msglvl_t msglevel, const uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es)
void options_string_import(struct options *options, const char *config, const msglvl_t msglevel, const uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es)
int parse_line(const char *line, char *p[], const int n, const char *file, const int line_num, msglvl_t msglevel, struct gc_arena *gc)
void read_config_file(struct options *options, const char *file, int level, const char *top_file, const int top_line, const msglvl_t msglevel, const uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es)
static int check_inline_file_via_fp(FILE *fp, char *p[], struct gc_arena *gc)
bool apply_push_options(struct context *c, struct options *options, struct buffer *buf, uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es, bool is_update)
void read_config_string(const char *prefix, struct options *options, const char *config, const msglvl_t msglevel, const uint64_t permission_mask, uint64_t *option_types_found, struct env_set *es)
static char * read_inline_file(struct in_src *is, const char *close_tag, int *num_lines, struct gc_arena *gc)
bool check_push_update_option_flags(char *line, int *i, uint64_t *flags)
Checks the formatting and validity of options inside push-update messages.
bool apply_pull_filter(const struct options *o, char *line)
Filter an option line by all pull filters.
#define PUSH_OPT_TO_REMOVE
#define PUSH_OPT_OPTIONAL
Wrapper structure for dynamically allocated memory.
int capacity
Size in bytes of memory allocated by malloc().
Contains all state information for one tunnel.
Garbage collection arena used to keep track of dynamically allocated memory.
struct buffer * multiline
union in_src::@226311311145304014152164131202304134072003123370 u