diff --git a/include/parser.h b/include/parser.h index f93e3e386d..9c0cf0ecd3 100644 --- a/include/parser.h +++ b/include/parser.h @@ -1,6 +1,6 @@ /* * ProFTPD - FTP server daemon - * Copyright (c) 2004-2011 The ProFTPD Project team + * Copyright (c) 2004-2015 The ProFTPD Project team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,9 +22,7 @@ * OpenSSL in the source distribution. */ -/* Configuration parser - * $Id: parser.h,v 1.4 2011-05-23 20:35:35 castaglia Exp $ - */ +/* Configuration parser */ #ifndef PR_PARSER_H #define PR_PARSER_H @@ -60,8 +58,7 @@ config_rec *pr_parser_config_ctxt_get(void); */ config_rec *pr_parser_config_ctxt_open(const char *name); -/* Returns the line number of the configuration stream being parsed. - */ +/* Returns the line number of the configuration stream being parsed. */ unsigned int pr_parser_get_lineno(void); /* This is the main function to be used by consumers of the Parser @@ -85,12 +82,11 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start, #define PR_PARSER_FL_DYNAMIC_CONFIG 0x0001 /* The dispatching of configuration data to the registered configuration - * handlers is done using a cmd_rec. This function calls pr_parse_read_line() - * to obtain the next line of configuration text, then allocates a cmd_rec - * from the given pool p and populates the struct with data from the - * line of text. + * handlers is done using a cmd_rec. This function parses the given line of + * text, then allocates a cmd_rec from the given pool p and populates the + * struct with data from the line of text. */ -cmd_rec *pr_parser_parse_line(pool *p); +cmd_rec *pr_parser_parse_line(pool *p, const char *text, size_t text_len); /* This convenience function reads the next line from the configuration * stream, performing any necessary transformations on the text (e.g. diff --git a/modules/mod_auth_unix.c b/modules/mod_auth_unix.c index e1c1e9b5f4..9a2d42921b 100644 --- a/modules/mod_auth_unix.c +++ b/modules/mod_auth_unix.c @@ -2,7 +2,7 @@ * ProFTPD - FTP server daemon * Copyright (c) 1997, 1998 Public Flood Software * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu - * Copyright (c) 2001-2014 The ProFTPD Project team + * Copyright (c) 2001-2015 The ProFTPD Project team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,8 +24,7 @@ * the source code for OpenSSL in the source distribution. */ -/* Unix authentication module for ProFTPD - */ +/* Unix authentication module for ProFTPD */ #include "conf.h" @@ -1120,7 +1119,8 @@ MODRET pw_getgroups(cmd_rec *cmd) { "using getgrouplist(3) to look up group membership"); memset(group_ids, 0, sizeof(group_ids)); - if (getgrouplist(pw->pw_name, pw->pw_gid, group_ids, &ngroups) < 0) { + if (getgrouplist(pw->pw_name, pw->pw_gid, (int *) group_ids, + &ngroups) < 0) { int xerrno = errno; pr_log_pri(PR_LOG_WARNING, "getgrouplist error: %s", strerror(xerrno)); diff --git a/modules/mod_core.c b/modules/mod_core.c index 5fdea420e9..1ec73993dc 100644 --- a/modules/mod_core.c +++ b/modules/mod_core.c @@ -363,7 +363,7 @@ MODRET add_include(cmd_rec *cmd) { "unable to use path for configuration file '", cmd->argv[1], "'", NULL)); } - if (parse_config_path(cmd->tmp_pool, cmd->argv[1]) == -1) { + if (parse_config_path(cmd->tmp_pool, cmd->argv[1]) < 0) { int xerrno = errno; if (xerrno != EINVAL) { diff --git a/src/main.c b/src/main.c index 729ca030c8..f63cf48d00 100644 --- a/src/main.c +++ b/src/main.c @@ -949,13 +949,20 @@ void restart_daemon(void *d1, void *d2, void *d3, void *d4) { pr_event_generate("core.preparse", NULL); PRIVS_ROOT - if (pr_parser_parse_file(NULL, config_filename, NULL, 0) == -1) { + if (pr_parser_parse_file(NULL, config_filename, NULL, 0) < 0) { int xerrno = errno; PRIVS_RELINQUISH - pr_log_pri(PR_LOG_WARNING, - "fatal: unable to read configuration file '%s': %s", config_filename, - strerror(xerrno)); + + /* Note: EPERM is used to indicate the presence of unrecognized + * configuration directives in the parsed file(s). + */ + if (xerrno != EPERM) { + pr_log_pri(PR_LOG_WARNING, + "fatal: unable to read configuration file '%s': %s", config_filename, + strerror(xerrno)); + } + pr_session_end(0); } PRIVS_RELINQUISH @@ -2406,10 +2413,16 @@ int main(int argc, char *argv[], char **envp) { pr_event_generate("core.preparse", NULL); - if (pr_parser_parse_file(NULL, config_filename, NULL, 0) == -1) { - pr_log_pri(PR_LOG_WARNING, - "fatal: unable to read configuration file '%s': %s", config_filename, - strerror(errno)); + if (pr_parser_parse_file(NULL, config_filename, NULL, 0) < 0) { + /* Note: EPERM is used to indicate the presence of unrecognized + * configuration directives in the parsed file(s). + */ + if (errno != EPERM) { + pr_log_pri(PR_LOG_WARNING, + "fatal: unable to read configuration file '%s': %s", config_filename, + strerror(errno)); + } + exit(1); } diff --git a/src/parser.c b/src/parser.c index 931984697c..4d1b564089 100644 --- a/src/parser.c +++ b/src/parser.c @@ -331,6 +331,7 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start, cmd_rec *cmd; pool *tmp_pool; char *report_path; + char buf[PR_TUNABLE_BUFFER_SIZE+1]; if (path == NULL) { errno = EINVAL; @@ -341,11 +342,13 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start, pr_pool_tag(tmp_pool, "parser file pool"); report_path = (char *) path; - if (session.chroot_path) + if (session.chroot_path) { report_path = pdircat(tmp_pool, session.chroot_path, path, NULL); + } - if (!(flags & PR_PARSER_FL_DYNAMIC_CONFIG)) + if (!(flags & PR_PARSER_FL_DYNAMIC_CONFIG)) { pr_trace_msg(trace_channel, 3, "parsing '%s' configuration", report_path); + } fh = pr_fsio_open(path, O_RDONLY); if (fh == NULL) { @@ -398,9 +401,15 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start, add_config_ctxt(start); } - while ((cmd = pr_parser_parse_line(tmp_pool)) != NULL) { + memset(buf, '\0', sizeof(buf)); + while (pr_parser_read_line(buf, sizeof(buf)-1) != NULL) { pr_signals_handle(); + cmd = pr_parser_parse_line(tmp_pool, buf, 0); + if (cmd == NULL) { + continue; + } + if (cmd->argc) { conftable *conftab; char found = FALSE; @@ -425,11 +434,11 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start, mr = pr_module_call(conftab->m, conftab->handler, cmd); if (mr != NULL) { if (MODRET_ISERROR(mr)) { - if (!(flags & PR_PARSER_FL_DYNAMIC_CONFIG)) { pr_log_pri(PR_LOG_WARNING, "fatal: %s on line %u of '%s'", MODRET_ERRMSG(mr), cs->cs_lineno, report_path); - exit(1); + errno = EPERM; + return -1; } else { pr_log_pri(PR_LOG_WARNING, "warning: %s on line %u of '%s'", @@ -486,7 +495,8 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start, "'%s' (contains non-ASCII characters)", name); } - exit(1); + errno = EPERM; + return -1; } pr_log_pri(PR_LOG_WARNING, "warning: unknown configuration directive " @@ -499,6 +509,7 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start, } destroy_pool(cmd->pool); + memset(buf, '\0', sizeof(buf)); } /* Pop this configuration stream from the stack. */ @@ -510,101 +521,106 @@ int pr_parser_parse_file(pool *p, const char *path, config_rec *start, return 0; } -cmd_rec *pr_parser_parse_line(pool *p) { +cmd_rec *pr_parser_parse_line(pool *p, const char *text, size_t text_len) { register unsigned int i; - char buf[PR_TUNABLE_BUFFER_SIZE+1], *arg = "", *word = NULL; + char *arg = "", *ptr, *word = NULL; cmd_rec *cmd = NULL; pool *sub_pool = NULL; array_header *arr = NULL; - if (p == NULL) { + if (p == NULL || + text == NULL) { errno = EINVAL; return NULL; } - memset(buf, '\0', sizeof(buf)); - - while (pr_parser_read_line(buf, sizeof(buf)-1) != NULL) { - char *bufp = buf; + if (text_len == 0) { + text_len = strlen(text); + } - pr_signals_handle(); + if (text_len == 0) { + errno = ENOENT; + return NULL; + } - /* Build a new pool for the command structure and array */ - sub_pool = make_sub_pool(p); - pr_pool_tag(sub_pool, "parser cmd subpool"); + ptr = (char *) text; - cmd = pcalloc(sub_pool, sizeof(cmd_rec)); - cmd->pool = sub_pool; - cmd->stash_index = -1; - cmd->stash_hash = 0; + /* Build a new pool for the command structure and array */ + sub_pool = make_sub_pool(p); + pr_pool_tag(sub_pool, "parser cmd subpool"); - /* Add each word to the array */ - arr = make_array(cmd->pool, 4, sizeof(char **)); - while ((word = pr_str_get_word(&bufp, 0)) != NULL) { - char *tmp; + cmd = pcalloc(sub_pool, sizeof(cmd_rec)); + cmd->pool = sub_pool; + cmd->stash_index = -1; + cmd->stash_hash = 0; - tmp = get_config_word(cmd->pool, word); + /* Add each word to the array */ + arr = make_array(cmd->pool, 4, sizeof(char **)); + while ((word = pr_str_get_word(&ptr, 0)) != NULL) { + char *ptr2; - *((char **) push_array(arr)) = tmp; - cmd->argc++; - } + pr_signals_handle(); + ptr2 = get_config_word(cmd->pool, word); + *((char **) push_array(arr)) = ptr2; + cmd->argc++; + } - /* Terminate the array with a NULL. */ - *((char **) push_array(arr)) = NULL; + /* Terminate the array with a NULL. */ + *((char **) push_array(arr)) = NULL; - /* The array header's job is done, we can forget about it and - * it will get purged when the command's pool is destroyed. - */ + /* The array header's job is done, we can forget about it and + * it will get purged when the command's pool is destroyed. + */ - cmd->argv = (void **) arr->elts; + cmd->argv = (void **) arr->elts; - /* Perform a fixup on configuration directives so that: - * - * -argv[0]-- -argv[1]-- ----argv[2]----- - *