Blob Blame History Raw
autofs-5.0.4 - fix map type info parse error update

From: Ian Kent <raven@themaw.net>

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 <ctype.h>
 #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++;