autofs-5.0.4 - fix map type info parse error update From: Ian Kent Make parsing map type info more robust. --- lib/parse_subs.c | 123 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 102 insertions(+), 21 deletions(-) diff --git a/lib/parse_subs.c b/lib/parse_subs.c index 0608cb7..2326838 100644 --- a/lib/parse_subs.c +++ b/lib/parse_subs.c @@ -20,6 +20,30 @@ #include #include "automount.h" +struct types { + char *type; + unsigned int len; +}; + +static struct types map_type[] = { + { "file", 4 }, + { "program", 7 }, + { "yp", 2 }, + { "nis", 3 }, + { "nisplus", 7 }, + { "ldap", 4 }, + { "ldaps", 5 }, + { "hesiod", 6 }, + { "userdir", 7 }, +}; +static unsigned int map_type_count = sizeof(map_type)/sizeof(struct types); + +static struct types format_type[] = { + { "sun", 3 }, + { "hesiod", 6 }, +}; +static unsigned int format_type_count = sizeof(format_type)/sizeof(struct types); + /* * Skip whitespace in a string; if we hit a #, consider the rest of the * entry a comment. @@ -315,7 +339,7 @@ struct map_type_info *parse_map_type_info(const char *str) { struct map_type_info *info; char *buf, *type, *fmt, *map, *tmp; - int seen_colon = 0; + char *pos; buf = strdup(str); if (!buf) @@ -328,32 +352,89 @@ struct map_type_info *parse_map_type_info(const char *str) } memset(info, 0, sizeof(struct map_type_info)); - type = fmt = NULL; + type = fmt = map = NULL; + + tmp = strchr(buf, ':'); + if (!tmp) { + pos = buf; + while (*pos == ' ') + *pos++ = '\0'; + map = pos; + } else { + int i, j; + + for (i = 0; i < map_type_count; i++) { + char *m_type = map_type[i].type; + unsigned int m_len = map_type[i].len; + + pos = buf; + + if (strncmp(m_type, pos, m_len)) + continue; + + type = pos; + pos += m_len; + + if (*pos == ' ' || *pos == ':') { + while (*pos == ' ') + *pos++ = '\0'; + if (*pos != ':') { + free(buf); + free(info); + return NULL; + } else { + *pos++ = '\0'; + while (*pos == ' ') + *pos++ = '\0'; + map = pos; + break; + } + } + + if (*pos == ',') { + *pos++ = '\0'; + for (j = 0; j < format_type_count; j++) { + char *f_type = format_type[j].type; + unsigned int f_len = format_type[j].len; + + if (strncmp(f_type, pos, f_len)) + continue; + + fmt = pos; + pos += f_len; + + if (*pos == ' ' || *pos == ':') { + while (*pos == ' ') + *pos++ = '\0'; + if (*pos != ':') { + free(buf); + free(info); + return NULL; + } else { + *pos++ = '\0'; + while (*pos == ' ') + *pos++ = '\0'; + map = pos; + break; + } + } + } + } + } + + if (!type) { + pos = buf; + while (*pos == ' ') + *pos++ = '\0'; + map = pos; + } + } /* Look for space terminator - ignore local options */ - map = buf; for (tmp = buf; *tmp; tmp++) { if (*tmp == ' ') { *tmp = '\0'; break; - } else if (!seen_colon && *tmp == ',') { - type = buf; - *tmp++ = '\0'; - fmt = tmp; - } else if (*tmp == ':') { - seen_colon = 1; - if (!fmt) - type = buf; - *tmp++ = '\0'; - map = tmp; - } else if (*tmp == '[') { - /* - * Unescaped '[' is a syntax error here as only - * an ldap map with a type specified should contain - * them. - */ - free(buf); - return 0; } if (*tmp == '\\') tmp++;