]>
Commit | Line | Data |
---|---|---|
e5fd101c PS |
1 | autofs-5.0.4 - ipv6 parse |
2 | ||
3 | From: Ian Kent <raven@themaw.net> | |
4 | ||
5 | Since ipv6 addresses use a colon separator and we use the colon quite a | |
6 | bit as a delimiting character we need to distinguish between when the | |
7 | colon is the delimeter we are looking for and when it is part of an ipv6 | |
8 | address. Since there is widespread use of "[" and "]" to provide the | |
9 | ability to separate a port specification from an ipv6 address this | |
10 | convention has also been used in autofs. | |
11 | --- | |
12 | ||
13 | include/parse_subs.h | 8 ++++ | |
14 | lib/master_tok.l | 10 +++-- | |
15 | lib/parse_subs.c | 99 +++++++++++++++++++++++++++++++++++++++++++++--- | |
16 | modules/lookup_file.c | 40 +++++++------------ | |
17 | modules/lookup_ldap.c | 21 +++++++++- | |
18 | modules/mount_autofs.c | 29 ++++++-------- | |
19 | modules/parse_sun.c | 16 +++++--- | |
20 | modules/replicated.c | 26 ++++++++++++- | |
21 | 8 files changed, 186 insertions(+), 63 deletions(-) | |
22 | ||
23 | ||
24 | diff --git a/include/parse_subs.h b/include/parse_subs.h | |
25 | index 643ad68..ecc712d 100644 | |
26 | --- a/include/parse_subs.h | |
27 | +++ b/include/parse_subs.h | |
28 | @@ -20,6 +20,12 @@ | |
29 | ||
30 | struct mapent; | |
31 | ||
32 | +struct map_type_info { | |
33 | + char *type; | |
34 | + char *format; | |
35 | + char *map; | |
36 | +}; | |
37 | + | |
38 | const char *skipspace(const char *); | |
39 | int check_colon(const char *); | |
40 | int chunklen(const char *, int); | |
41 | @@ -27,5 +33,7 @@ int strmcmp(const char *, const char *, int); | |
42 | char *dequote(const char *, int, unsigned int); | |
43 | int span_space(const char *, unsigned int); | |
44 | char *sanitize_path(const char *, int, unsigned int, unsigned int); | |
45 | +void free_map_type_info(struct map_type_info *); | |
46 | +struct map_type_info *parse_map_type_info(const char *); | |
47 | ||
48 | #endif | |
49 | diff --git a/lib/master_tok.l b/lib/master_tok.l | |
50 | index 801aa6f..b6cc8be 100644 | |
51 | --- a/lib/master_tok.l | |
52 | +++ b/lib/master_tok.l | |
53 | @@ -96,10 +96,12 @@ SLASHIFYSTR (--(no-)?slashify-colons) | |
54 | NUMBER [0-9]+ | |
55 | ||
56 | DNSERVSTR1 ([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:) | |
57 | -DNSERVSTR2 (\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/) | |
58 | -DNSERVSTR3 (([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:) | |
59 | -DNSERVSTR4 (\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/) | |
60 | -DNSERVERSTR ({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}) | |
61 | +DNSERVSTR2 (\[([[:xdigit:]]:.)+\](:[0-9]+)?:) | |
62 | +DNSERVSTR3 (\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/) | |
63 | +DNSERVSTR4 (\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/) | |
64 | +DNSERVSTR5 (([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:) | |
65 | +DNSERVSTR6 (\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/) | |
66 | +DNSERVERSTR ({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6}) | |
67 | ||
68 | AT_CN ([cC][[nN]) | |
69 | AT_NMN ([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE]) | |
70 | diff --git a/lib/parse_subs.c b/lib/parse_subs.c | |
71 | index 8a032e8..0cba95a 100644 | |
72 | --- a/lib/parse_subs.c | |
73 | +++ b/lib/parse_subs.c | |
74 | @@ -56,14 +56,13 @@ int check_colon(const char *str) | |
75 | char *ptr = (char *) str; | |
76 | ||
77 | /* Colon escape */ | |
78 | - if (*ptr == ':') | |
79 | + if (!strncmp(ptr, ":/", 2)) | |
80 | return 1; | |
81 | ||
82 | - while (*ptr && *ptr != ':' && *ptr != '/') { | |
83 | + while (*ptr && strncmp(ptr, ":/", 2)) | |
84 | ptr++; | |
85 | - } | |
86 | ||
87 | - if (!*ptr || *ptr == '/') | |
88 | + if (!*ptr) | |
89 | return 0; | |
90 | ||
91 | return 1; | |
92 | @@ -93,12 +92,12 @@ int chunklen(const char *whence, int expect_colon) | |
93 | n++; | |
94 | if (*str == '"') | |
95 | break; | |
96 | - if (*str == ':') | |
97 | + if (!strncmp(str, ":/", 2)) | |
98 | expect_colon = 0; | |
99 | } | |
100 | break; | |
101 | case ':': | |
102 | - if (expect_colon) | |
103 | + if (expect_colon && !strncmp(str, ":/", 2)) | |
104 | expect_colon = 0; | |
105 | continue; | |
106 | case ' ': | |
107 | @@ -300,3 +299,91 @@ char *sanitize_path(const char *path, int origlen, unsigned int type, unsigned i | |
108 | return s_path; | |
109 | } | |
110 | ||
111 | +void free_map_type_info(struct map_type_info *info) | |
112 | +{ | |
113 | + if (info->type) | |
114 | + free(info->type); | |
115 | + if (info->format) | |
116 | + free(info->format); | |
117 | + if (info->map) | |
118 | + free(info->map); | |
119 | + free(info); | |
120 | + return; | |
121 | +} | |
122 | + | |
123 | +struct map_type_info *parse_map_type_info(const char *str) | |
124 | +{ | |
125 | + struct map_type_info *info; | |
126 | + char *buf, *type, *fmt, *map, *tmp; | |
127 | + | |
128 | + buf = strdup(str); | |
129 | + if (!buf) | |
130 | + return NULL; | |
131 | + | |
132 | + info = malloc(sizeof(struct map_type_info)); | |
133 | + if (!info) { | |
134 | + free(buf); | |
135 | + return NULL; | |
136 | + } | |
137 | + memset(info, 0, sizeof(struct map_type_info)); | |
138 | + | |
139 | + type = fmt = NULL; | |
140 | + | |
141 | + /* Look for space terminator - ignore local options */ | |
142 | + map = buf; | |
143 | + for (tmp = buf; *tmp; tmp++) { | |
144 | + if (*tmp == ' ') { | |
145 | + *tmp = '\0'; | |
146 | + break; | |
147 | + } else if (*tmp == ',') { | |
148 | + type = buf; | |
149 | + *tmp++ = '\0'; | |
150 | + fmt = tmp; | |
151 | + } else if (*tmp == ':') { | |
152 | + if (!fmt) | |
153 | + type = buf; | |
154 | + *tmp++ = '\0'; | |
155 | + map = tmp; | |
156 | + } else if (*tmp == '[') { | |
157 | + /* | |
158 | + * Unescaped '[' is a syntax error here as only | |
159 | + * an ldap map with a type specified should contain | |
160 | + * them. | |
161 | + */ | |
162 | + free(buf); | |
163 | + return 0; | |
164 | + } | |
165 | + if (*tmp == '\\') | |
166 | + tmp++; | |
167 | + } | |
168 | + | |
169 | + if (type) { | |
170 | + info->type = strdup(type); | |
171 | + if (!info->type) { | |
172 | + free(buf); | |
173 | + free_map_type_info(info); | |
174 | + return NULL; | |
175 | + } | |
176 | + } | |
177 | + | |
178 | + if (fmt) { | |
179 | + info->format = strdup(fmt); | |
180 | + if (!info->format) { | |
181 | + free(buf); | |
182 | + free_map_type_info(info); | |
183 | + return NULL; | |
184 | + } | |
185 | + } | |
186 | + | |
187 | + info->map = strdup(map); | |
188 | + if (!info->map) { | |
189 | + free(buf); | |
190 | + free_map_type_info(info); | |
191 | + return NULL; | |
192 | + } | |
193 | + | |
194 | + free(buf); | |
195 | + | |
196 | + return info; | |
197 | +} | |
198 | + | |
199 | diff --git a/modules/lookup_file.c b/modules/lookup_file.c | |
200 | index ba80f2a..ec78090 100644 | |
201 | --- a/modules/lookup_file.c | |
202 | +++ b/modules/lookup_file.c | |
203 | @@ -523,10 +523,10 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in | |
204 | { | |
205 | struct map_source *current; | |
206 | struct map_source *source; | |
207 | - char *type, *map, *fmt; | |
208 | + struct map_type_info *info; | |
209 | const char *argv[2]; | |
210 | int argc; | |
211 | - char *buf, *tmp; | |
212 | + char *buf; | |
213 | ||
214 | current = ap->entry->current; | |
215 | ap->entry->current = NULL; | |
216 | @@ -548,33 +548,19 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in | |
217 | return NULL; | |
218 | } | |
219 | ||
220 | - type = fmt = NULL; | |
221 | - | |
222 | - /* Look for space terminator - ignore local options */ | |
223 | - map = buf; | |
224 | - for (tmp = buf; *tmp; tmp++) { | |
225 | - if (*tmp == ' ') { | |
226 | - *tmp = '\0'; | |
227 | - break; | |
228 | - } else if (*tmp == ',') { | |
229 | - type = buf; | |
230 | - *tmp++ = '\0'; | |
231 | - fmt = tmp; | |
232 | - } else if (*tmp == ':') { | |
233 | - if (!fmt) | |
234 | - type = buf; | |
235 | - *tmp++ = '\0'; | |
236 | - map = tmp; | |
237 | - } | |
238 | - if (*tmp == '\\') | |
239 | - tmp++; | |
240 | + if (!(info = parse_map_type_info(buf))) { | |
241 | + error(ap->logopt, MODPREFIX "failed to parse map info"); | |
242 | + free(buf); | |
243 | + return NULL; | |
244 | } | |
245 | ||
246 | argc = 1; | |
247 | - argv[0] = map; | |
248 | + argv[0] = info->map; | |
249 | argv[1] = NULL; | |
250 | ||
251 | - source = master_find_source_instance(current, type, fmt, argc, argv); | |
252 | + source = master_find_source_instance(current, | |
253 | + info->type, info->format, | |
254 | + argc, argv); | |
255 | if (source) | |
256 | /* | |
257 | * Make sure included map age is in sync with its owner | |
258 | @@ -582,8 +568,11 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in | |
259 | */ | |
260 | source->age = age; | |
261 | else { | |
262 | - source = master_add_source_instance(current, type, fmt, age, argc, argv); | |
263 | + source = master_add_source_instance(current, | |
264 | + info->type, info->format, | |
265 | + age, argc, argv); | |
266 | if (!source) { | |
267 | + free_map_type_info(info); | |
268 | free(buf); | |
269 | error(ap->logopt, "failed to add included map instance"); | |
270 | return NULL; | |
271 | @@ -594,6 +583,7 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in | |
272 | if (inc) | |
273 | source->recurse = 1; | |
274 | ||
275 | + free_map_type_info(info); | |
276 | free(buf); | |
277 | ||
278 | return source; | |
279 | diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c | |
280 | index 094cbdc..7845bcf 100644 | |
281 | --- a/modules/lookup_ldap.c | |
282 | +++ b/modules/lookup_ldap.c | |
283 | @@ -1119,11 +1119,26 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c | |
284 | memcpy(ctxt->server, s, l); | |
285 | */ | |
286 | } | |
287 | - } else if (strchr(ptr, ':') != NULL) { | |
288 | - char *q = NULL; | |
289 | + } else if (strchr(ptr, ':') != NULL || *ptr == '[') { | |
290 | + const char *q = NULL; | |
291 | ||
292 | /* Isolate the server. Include the port spec */ | |
293 | - q = strchr(ptr, ':'); | |
294 | + if (*ptr != '[') | |
295 | + q = strchr(ptr, ':'); | |
296 | + else { | |
297 | + q = ++ptr; | |
298 | + while (*q == ':' || isxdigit(*q)) | |
299 | + q++; | |
300 | + if (*q != ']') { | |
301 | + crit(logopt, MODPREFIX | |
302 | + "invalid LDAP map syntax %s", ptr); | |
303 | + return 0; | |
304 | + } | |
305 | + q++; | |
306 | + if (*q == ':') | |
307 | + q++; | |
308 | + } | |
309 | + | |
310 | if (isdigit(*q)) | |
311 | while (isdigit(*q)) | |
312 | q++; | |
313 | diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c | |
314 | index fab2906..14d6307 100644 | |
315 | --- a/modules/mount_autofs.c | |
316 | +++ b/modules/mount_autofs.c | |
317 | @@ -50,7 +50,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, | |
318 | int argc, status, ghost = ap->flags & MOUNT_FLAG_GHOST; | |
319 | time_t timeout = ap->exp_timeout; | |
320 | unsigned logopt = ap->logopt; | |
321 | - char *type, *format, *tmp, *tmp2; | |
322 | + struct map_type_info *info; | |
323 | struct master *master; | |
324 | struct master_mapent *entry; | |
325 | struct map_source *source; | |
326 | @@ -174,21 +174,12 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, | |
327 | ||
328 | argc = 1; | |
329 | ||
330 | - type = NULL; | |
331 | - format = NULL; | |
332 | - | |
333 | - tmp = strchr(what, ':'); | |
334 | - if (tmp) { | |
335 | - *tmp++ = '\0'; | |
336 | - tmp2 = strchr(what, ','); | |
337 | - if (tmp2) { | |
338 | - *tmp2++ = '\0'; | |
339 | - format = tmp2; | |
340 | - } | |
341 | - type = (char *) what; | |
342 | - argv[0] = tmp; | |
343 | - } else | |
344 | - argv[0] = (char *) what; | |
345 | + if (!(info = parse_map_type_info(what))) { | |
346 | + error(ap->logopt, MODPREFIX "failed to parse map info"); | |
347 | + master_free_mapent(entry); | |
348 | + return 1; | |
349 | + } | |
350 | + argv[0] = info->map; | |
351 | ||
352 | if (options) { | |
353 | p = options; | |
354 | @@ -202,13 +193,17 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, | |
355 | } | |
356 | argv[argc] = NULL; | |
357 | ||
358 | - source = master_add_map_source(entry, type, format, time(NULL), argc, argv); | |
359 | + source = master_add_map_source(entry, | |
360 | + info->type, info->format, | |
361 | + time(NULL), argc, argv); | |
362 | if (!source) { | |
363 | error(ap->logopt, | |
364 | MODPREFIX "failed to add map source to entry"); | |
365 | master_free_mapent(entry); | |
366 | + free_map_type_info(info); | |
367 | return 1; | |
368 | } | |
369 | + free_map_type_info(info); | |
370 | ||
371 | source->mc = cache_init(entry->ap, source); | |
372 | if (!source->mc) { | |
373 | diff --git a/modules/parse_sun.c b/modules/parse_sun.c | |
374 | index ed73e46..65417e1 100644 | |
375 | --- a/modules/parse_sun.c | |
376 | +++ b/modules/parse_sun.c | |
377 | @@ -245,7 +245,9 @@ int expandsunent(const char *src, char *dst, const char *key, | |
378 | *(dst++) = | |
379 | (seen_colons && slashify_colons) ? '/' : ':'; | |
380 | len++; | |
381 | - seen_colons = 1; | |
382 | + /* Were looking for the colon preceeding a path */ | |
383 | + if (*src == '/') | |
384 | + seen_colons = 1; | |
385 | break; | |
386 | ||
387 | default: | |
388 | @@ -814,21 +816,23 @@ static int validate_location(char *loc) | |
389 | return 1; | |
390 | ||
391 | /* | |
392 | - * If a ':' is present now it must be a host name, except | |
393 | + * If a ':/' is present now it must be a host name, except | |
394 | * for those special file systems like sshfs which use "#" | |
395 | - * and "@" in the host name part. | |
396 | + * and "@" in the host name part and ipv6 addresses that | |
397 | + * have ":", "[" and "]". | |
398 | */ | |
399 | if (check_colon(ptr)) { | |
400 | - while (*ptr && *ptr != ':') { | |
401 | + while (*ptr && strncmp(ptr, ":/", 2)) { | |
402 | if (!(isalnum(*ptr) || | |
403 | *ptr == '-' || *ptr == '.' || *ptr == '_' || | |
404 | *ptr == ',' || *ptr == '(' || *ptr == ')' || | |
405 | - *ptr == '#' || *ptr == '@')) | |
406 | + *ptr == '#' || *ptr == '@' || *ptr == ':' || | |
407 | + *ptr == '[' || *ptr == ']')) | |
408 | return 0; | |
409 | ptr++; | |
410 | } | |
411 | ||
412 | - if (*ptr && *ptr == ':') | |
413 | + if (*ptr && !strncmp(ptr, ":/", 2)) | |
414 | ptr++; | |
415 | } | |
416 | ||
417 | diff --git a/modules/replicated.c b/modules/replicated.c | |
418 | index 9e85c00..79845d0 100644 | |
419 | --- a/modules/replicated.c | |
420 | +++ b/modules/replicated.c | |
421 | @@ -1168,6 +1168,28 @@ static int add_local_path(struct host **hosts, const char *path) | |
422 | return 1; | |
423 | } | |
424 | ||
425 | +static char *seek_delim(const char *s) | |
426 | +{ | |
427 | + const char *p = s; | |
428 | + char *delim; | |
429 | + | |
430 | + delim = strpbrk(p, "(, \t:"); | |
431 | + if (delim && *delim != ':') | |
432 | + return delim; | |
433 | + | |
434 | + while (*p) { | |
435 | + if (*p != ':') { | |
436 | + p++; | |
437 | + continue; | |
438 | + } | |
439 | + if (!strncmp(p, ":/", 2)) | |
440 | + return (char *) p; | |
441 | + p++; | |
442 | + } | |
443 | + | |
444 | + return NULL; | |
445 | +} | |
446 | + | |
447 | int parse_location(unsigned logopt, struct host **hosts, const char *list) | |
448 | { | |
449 | char *str, *p, *delim; | |
450 | @@ -1187,7 +1209,7 @@ int parse_location(unsigned logopt, struct host **hosts, const char *list) | |
451 | int weight = 0; | |
452 | ||
453 | p += strspn(p, " \t,"); | |
454 | - delim = strpbrk(p, "(, \t:"); | |
455 | + delim = seek_delim(p); | |
456 | ||
457 | if (delim) { | |
458 | if (*delim == '(') { | |
459 | @@ -1211,7 +1233,7 @@ int parse_location(unsigned logopt, struct host **hosts, const char *list) | |
460 | ||
461 | /* Oh boy - might have spaces in the path */ | |
462 | next = path; | |
463 | - while (*next && *next != ':') | |
464 | + while (*next && strncmp(next, ":/", 2)) | |
465 | next++; | |
466 | ||
467 | /* No spaces in host names at least */ |